@agimon-ai/browse-tool 0.20.0 → 0.20.2

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.
@@ -199,6 +199,7 @@ async function locateElement(locator) {
199
199
  ];
200
200
  for (const element of semanticMatches) if (element) return element;
201
201
  if (locator.selector) {
202
+ if (/^uid=/.test(locator.selector.trim())) throw new Error(`UID selectors must use the uid field, for example {"uid":"${locator.selector.trim().slice(4)}"}. Snapshot UIDs are temporary, so take a new snapshot before retrying if it no longer resolves.`);
202
203
  const shortcut = parseSelectorShortcut(locator.selector);
203
204
  if (shortcut) {
204
205
  const element = findBySelectorShortcut(shortcut);
@@ -1 +1 @@
1
- {"version":3,"file":"content.js","names":[],"sources":["../../src/extension/content/element-locator.ts","../../src/extension/content/accessibility-tree.ts","../../src/extension/content/stealth.ts","../../src/extension/content/index.ts"],"sourcesContent":["/**\n * Element Locator - Strategies for finding elements in the DOM\n *\n * Supports multiple location strategies:\n * - CSS selector\n * - XPath\n * - Text content\n * - Accessibility UID (from snapshot)\n */\n\nexport interface ElementLocator {\n uid?: string;\n role?: string;\n name?: string;\n label?: string;\n placeholder?: string;\n text?: string;\n exact?: boolean;\n selector?: string;\n xpath?: string;\n testId?: string;\n}\n\nconst uidToElement = new Map<string, WeakRef<Element>>();\nlet uidCounter = 0;\n\ninterface SelectorShortcut {\n kind: 'text' | 'hasText';\n text: string;\n tagName?: string;\n exact: boolean;\n}\n\nexport function assignUid(element: Element): string {\n const uid = `e${++uidCounter}`;\n uidToElement.set(uid, new WeakRef(element));\n return uid;\n}\n\nexport function getElementByUid(uid: string): Element | null {\n const ref = uidToElement.get(uid);\n return ref?.deref() || null;\n}\n\nexport function clearUidMap(): void {\n uidToElement.clear();\n uidCounter = 0;\n}\n\nfunction normalizeText(value: string | null | undefined): string {\n return (value ?? '').replace(/\\s+/g, ' ').trim();\n}\n\nfunction matchesText(actual: string | null | undefined, expected: string, exact = false): boolean {\n const normalizedActual = normalizeText(actual);\n const normalizedExpected = normalizeText(expected);\n\n if (!normalizedActual || !normalizedExpected) {\n return false;\n }\n\n if (exact) {\n return normalizedActual === normalizedExpected;\n }\n\n return normalizedActual.toLowerCase().includes(normalizedExpected.toLowerCase());\n}\n\nfunction unquoteSelectorText(rawText: string): { text: string; exact: boolean } {\n const text = rawText.trim();\n const quote = text[0];\n if ((quote === '\"' || quote === \"'\") && text.endsWith(quote)) {\n return { text: text.slice(1, -1), exact: true };\n }\n return { text, exact: false };\n}\n\nfunction parseSelectorShortcut(selector: string): SelectorShortcut | null {\n const trimmed = selector.trim();\n\n if (trimmed.startsWith('text=')) {\n const parsed = unquoteSelectorText(trimmed.slice('text='.length));\n return { kind: 'text', text: parsed.text, exact: parsed.exact };\n }\n\n const hasTextMatch = trimmed.match(/^([a-zA-Z][\\w-]*)?:has-text\\((.*)\\)$/);\n if (hasTextMatch) {\n const parsed = unquoteSelectorText(hasTextMatch[2] ?? '');\n return {\n kind: 'hasText',\n tagName: hasTextMatch[1]?.toLowerCase(),\n text: parsed.text,\n exact: false,\n };\n }\n\n return null;\n}\n\nfunction formatUnsupportedSelectorError(selector: string, error: unknown): Error {\n const reason = error instanceof Error ? error.message : String(error);\n return new Error(\n `Unsupported CSS selector \"${selector}\": ${reason}. If you meant Playwright syntax, use text/name/role fields instead. Supported selector shortcuts are text=... and tag:has-text(\"...\").`,\n );\n}\n\nfunction getAssociatedControl(label: HTMLLabelElement): Element | null {\n if (label.control) {\n return label.control;\n }\n\n const forAttr = label.getAttribute('for');\n if (forAttr) {\n const target = document.getElementById(forAttr);\n if (target) {\n return target;\n }\n }\n\n return label.querySelector('input,select,textarea,button');\n}\n\n// NOTE: getRole / getAccessibleName are importable by content-script code.\n// For executeScript / page.evaluate callbacks, functions must be self-contained\n// (no imports). Keep those copies in sync with the canonical versions here.\n\nexport function getAccessibleName(element: Element): string {\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) {\n return normalizeText(ariaLabel);\n }\n\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const labels = labelledBy\n .split(/\\s+/)\n .map((id) => normalizeText(document.getElementById(id)?.textContent))\n .filter(Boolean);\n if (labels.length > 0) {\n return labels.join(' ');\n }\n }\n\n if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n if (element.id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(element.id)}\"]`);\n if (label?.textContent) {\n return normalizeText(label.textContent);\n }\n }\n if (element.placeholder) {\n return normalizeText(element.placeholder);\n }\n }\n\n const label = element.closest('label');\n if (label?.textContent) {\n return normalizeText(label.textContent);\n }\n\n if (element instanceof HTMLImageElement && element.alt) {\n return normalizeText(element.alt);\n }\n\n if (element.textContent) {\n return normalizeText(element.textContent);\n }\n\n return '';\n}\n\nexport function getRole(element: Element): string {\n const ariaRole = element.getAttribute('role');\n if (ariaRole) {\n return ariaRole;\n }\n\n if (element instanceof HTMLInputElement) {\n const type = (element.type || 'text').toLowerCase();\n const inputRoles: Record<string, string> = {\n button: 'button',\n checkbox: 'checkbox',\n email: 'textbox',\n number: 'spinbutton',\n password: 'textbox',\n radio: 'radio',\n range: 'slider',\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 tagName = element.tagName.toLowerCase();\n const roleMap: Record<string, string> = {\n a: element.hasAttribute('href') ? 'link' : 'none',\n article: 'article',\n aside: 'complementary',\n button: 'button',\n footer: 'contentinfo',\n form: 'form',\n h1: 'heading',\n h2: 'heading',\n h3: 'heading',\n h4: 'heading',\n h5: 'heading',\n h6: 'heading',\n header: 'banner',\n img: 'img',\n li: 'listitem',\n main: 'main',\n nav: 'navigation',\n ol: 'list',\n option: 'option',\n progress: 'progressbar',\n section: element.hasAttribute('aria-label') ? 'region' : 'none',\n select: 'combobox',\n table: 'table',\n td: 'cell',\n textarea: 'textbox',\n th: 'columnheader',\n tr: 'row',\n ul: 'list',\n };\n\n return roleMap[tagName] || 'none';\n}\n\nfunction allElements(): Element[] {\n return Array.from(document.querySelectorAll('*'));\n}\n\nfunction findByRole(locator: ElementLocator): Element | null {\n if (!locator.role) {\n return null;\n }\n\n const candidates = allElements().filter((element) => getRole(element) === locator.role);\n if (!locator.name) {\n return candidates[0] ?? null;\n }\n\n return candidates.find((element) => matchesText(getAccessibleName(element), locator.name!, locator.exact)) ?? null;\n}\n\nfunction findByLabel(locator: ElementLocator): Element | null {\n if (!locator.label) {\n return null;\n }\n\n const labels = Array.from(document.querySelectorAll('label')).filter((label) =>\n matchesText(label.textContent, locator.label!, locator.exact),\n );\n\n for (const label of labels) {\n const control = getAssociatedControl(label as HTMLLabelElement);\n if (control) {\n return control;\n }\n }\n\n return labels[0] ?? null;\n}\n\nfunction findByPlaceholder(locator: ElementLocator): Element | null {\n if (!locator.placeholder) {\n return null;\n }\n\n return (\n allElements().find((element) => {\n const placeholder = element.getAttribute('placeholder');\n return matchesText(placeholder, locator.placeholder!, locator.exact);\n }) ?? null\n );\n}\n\nfunction findByText(locator: ElementLocator): Element | null {\n if (!locator.text) {\n return null;\n }\n\n const candidates = allElements().filter((element) => matchesText(element.textContent, locator.text!, locator.exact));\n if (candidates.length === 0) {\n return null;\n }\n\n for (const candidate of candidates) {\n if (candidate instanceof HTMLLabelElement) {\n const control = getAssociatedControl(candidate);\n if (control) {\n return control;\n }\n }\n }\n\n return candidates[0];\n}\n\nfunction findByTestId(locator: ElementLocator): Element | null {\n if (!locator.testId) {\n return null;\n }\n\n return document.querySelector(`[data-testid=\"${CSS.escape(locator.testId)}\"]`);\n}\n\nfunction findBySelectorShortcut(shortcut: SelectorShortcut): Element | null {\n if (shortcut.kind === 'text') {\n return findByText({ text: shortcut.text, exact: shortcut.exact });\n }\n\n const elements = shortcut.tagName\n ? allElements().filter((element) => element.tagName.toLowerCase() === shortcut.tagName)\n : allElements();\n return elements.find((element) => matchesText(element.textContent, shortcut.text)) ?? null;\n}\n\nexport async function locateElement(locator: ElementLocator): Promise<Element | null> {\n // Try UID first (most precise)\n if (locator.uid) {\n const element = getElementByUid(locator.uid);\n if (element) return element;\n }\n\n // Try semantic selectors before raw DOM selectors.\n const semanticMatches = [\n findByRole(locator),\n findByLabel(locator),\n findByPlaceholder(locator),\n findByText(locator),\n findByTestId(locator),\n ];\n for (const element of semanticMatches) {\n if (element) {\n return element;\n }\n }\n\n // Try CSS selector\n if (locator.selector) {\n const shortcut = parseSelectorShortcut(locator.selector);\n if (shortcut) {\n const element = findBySelectorShortcut(shortcut);\n if (element) return element;\n } else {\n try {\n const element = document.querySelector(locator.selector);\n if (element) return element;\n } catch (error) {\n throw formatUnsupportedSelectorError(locator.selector, error);\n }\n }\n }\n\n // Try XPath\n if (locator.xpath) {\n const result = document.evaluate(locator.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);\n if (result.singleNodeValue instanceof Element) {\n return result.singleNodeValue;\n }\n }\n\n // Try explicit accessible name lookup if a name is provided without role.\n if (locator.name) {\n const element = allElements().find((candidate) =>\n matchesText(getAccessibleName(candidate), locator.name!, locator.exact),\n );\n if (element) {\n return element;\n }\n }\n\n return null;\n}\n","/**\n * Accessibility Tree Builder\n *\n * Generates an accessibility snapshot of the page,\n * similar to Playwright's accessibility tree format.\n */\n\nimport { assignUid, clearUidMap } from './element-locator.js';\n\nexport interface AccessibilityNode {\n uid: string;\n role: string;\n name?: string;\n value?: string;\n description?: string;\n children?: AccessibilityNode[];\n focused?: boolean;\n disabled?: boolean;\n checked?: boolean | 'mixed';\n selected?: boolean;\n expanded?: boolean;\n level?: number;\n pressed?: boolean | 'mixed';\n}\n\nexport function buildAccessibilityTree(rootSelector?: string): AccessibilityNode {\n // Clear previous UID assignments\n clearUidMap();\n\n const rootElement = rootSelector ? (document.querySelector(rootSelector) ?? document.body) : document.body;\n const root = buildNode(rootElement as Element, 0);\n return root || { uid: 'root', role: 'none', name: 'Empty page' };\n}\n\nfunction buildNode(element: Element, depth: number): AccessibilityNode | null {\n // Skip hidden elements\n const style = getComputedStyle(element);\n if (style.display === 'none' || style.visibility === 'hidden') {\n return null;\n }\n\n const role = getRole(element);\n const name = getAccessibleName(element);\n const uid = assignUid(element);\n\n // Build children\n const children: AccessibilityNode[] = [];\n for (const child of element.children) {\n const childNode = buildNode(child, depth + 1);\n if (childNode) {\n children.push(childNode);\n }\n }\n\n // Skip non-semantic containers with no accessible name\n if (role === 'none' && !name && children.length === 1) {\n return children[0];\n }\n\n const node: AccessibilityNode = {\n uid,\n role,\n };\n\n if (name) node.name = name;\n if (children.length > 0) node.children = children;\n\n // Add state properties\n addStateProperties(element, node);\n\n return node;\n}\n\nfunction getRole(element: Element): string {\n // Explicit ARIA role\n const ariaRole = element.getAttribute('role');\n if (ariaRole) return ariaRole;\n\n // Implicit roles based on tag name\n const tagName = element.tagName.toLowerCase();\n const roleMap: Record<string, string> = {\n a: element.hasAttribute('href') ? 'link' : 'none',\n article: 'article',\n aside: 'complementary',\n button: 'button',\n footer: 'contentinfo',\n form: 'form',\n h1: 'heading',\n h2: 'heading',\n h3: 'heading',\n h4: 'heading',\n h5: 'heading',\n h6: 'heading',\n header: 'banner',\n img: 'img',\n input: getInputRole(element as HTMLInputElement),\n li: 'listitem',\n main: 'main',\n nav: 'navigation',\n ol: 'list',\n option: 'option',\n progress: 'progressbar',\n section: element.hasAttribute('aria-label') ? 'region' : 'none',\n select: 'combobox',\n table: 'table',\n tbody: 'rowgroup',\n td: 'cell',\n textarea: 'textbox',\n th: 'columnheader',\n tr: 'row',\n ul: 'list',\n };\n\n return roleMap[tagName] || 'none';\n}\n\nfunction getInputRole(input: HTMLInputElement): string {\n const type = (input.type || 'text').toLowerCase();\n const inputRoles: Record<string, string> = {\n button: 'button',\n checkbox: 'checkbox',\n email: 'textbox',\n number: 'spinbutton',\n password: 'textbox',\n radio: 'radio',\n range: 'slider',\n search: 'searchbox',\n submit: 'button',\n tel: 'textbox',\n text: 'textbox',\n url: 'textbox',\n };\n return inputRoles[type] || 'textbox';\n}\n\nfunction getAccessibleName(element: Element): string | undefined {\n // aria-label\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel;\n\n // aria-labelledby\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const labels = labelledBy\n .split(' ')\n .map((id) => document.getElementById(id)?.textContent)\n .filter(Boolean)\n .join(' ');\n if (labels) return labels;\n }\n\n // For inputs, check associated label\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n const id = element.id;\n if (id) {\n const label = document.querySelector(`label[for=\"${id}\"]`);\n if (label?.textContent) return label.textContent.trim();\n }\n }\n\n // Text content for certain elements\n const tagName = element.tagName.toLowerCase();\n if (['button', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'label', 'option'].includes(tagName)) {\n const text = element.textContent?.trim();\n if (text && text.length < 100) return text;\n }\n\n // Alt text for images\n if (element instanceof HTMLImageElement && element.alt) {\n return element.alt;\n }\n\n // Placeholder for inputs\n if (element instanceof HTMLInputElement && element.placeholder) {\n return element.placeholder;\n }\n\n return undefined;\n}\n\nfunction addStateProperties(element: Element, node: AccessibilityNode): void {\n // Focus state\n if (document.activeElement === element) {\n node.focused = true;\n }\n\n // Disabled state\n if ((element as HTMLInputElement).disabled) {\n node.disabled = true;\n }\n\n // Checked state\n if (element instanceof HTMLInputElement) {\n if (element.type === 'checkbox' || element.type === 'radio') {\n node.checked = element.indeterminate ? 'mixed' : element.checked;\n }\n }\n\n // Selected state\n if (element instanceof HTMLOptionElement) {\n node.selected = element.selected;\n }\n\n // Expanded state\n const ariaExpanded = element.getAttribute('aria-expanded');\n if (ariaExpanded) {\n node.expanded = ariaExpanded === 'true';\n }\n\n // Heading level\n const headingMatch = element.tagName.match(/^H([1-6])$/);\n if (headingMatch) {\n node.level = Number.parseInt(headingMatch[1], 10);\n }\n\n // Pressed state\n const ariaPressed = element.getAttribute('aria-pressed');\n if (ariaPressed) {\n node.pressed = ariaPressed === 'mixed' ? 'mixed' : ariaPressed === 'true';\n }\n}\n","/**\n * Stealth overrides injected into the MAIN world before page scripts run.\n * Masks automation signals that anti-bot systems (TikTok, etc.) detect.\n */\n\nexport function installStealthOverrides(): void {\n const marker = '__browseToolStealthInstalled__';\n if ((globalThis as Record<string, unknown>)[marker]) {\n return;\n }\n (globalThis as Record<string, unknown>)[marker] = true;\n\n const overrides = () => {\n const w = window as typeof window & { __browseToolStealthInstalled__?: boolean };\n if (w.__browseToolStealthInstalled__) {\n return;\n }\n w.__browseToolStealthInstalled__ = true;\n\n // 1. Mask navigator.webdriver\n Object.defineProperty(navigator, 'webdriver', {\n get: () => undefined,\n configurable: true,\n });\n\n // 2. Normalize navigator.hardwareConcurrency (Docker containers often expose 1-2 cores)\n if (navigator.hardwareConcurrency < 4) {\n Object.defineProperty(navigator, 'hardwareConcurrency', {\n get: () => 8,\n configurable: true,\n });\n }\n\n // 3. Override permissions.query to return \"prompt\" for notifications\n // Chrome for Testing defaults to \"denied\" which is a known fingerprint.\n const originalQuery = navigator.permissions.query.bind(navigator.permissions);\n navigator.permissions.query = (descriptor: PermissionDescriptor) => {\n if (descriptor.name === 'notifications') {\n return Promise.resolve({ state: 'prompt', onchange: null } as PermissionStatus);\n }\n return originalQuery(descriptor);\n };\n\n // 4. Spoof navigator.plugins with realistic entries (empty plugins = headless signal)\n const pluginCount = (navigator as { plugins: { length: number } }).plugins.length;\n if (pluginCount === 0) {\n Object.defineProperty(navigator, 'plugins', {\n get: () => {\n const plugins = [\n { name: 'PDF Viewer', filename: 'internal-pdf-viewer', description: 'Portable Document Format' },\n {\n name: 'Chrome PDF Plugin',\n filename: 'internal-pdf-viewer',\n description: 'Portable Document Format',\n },\n {\n name: 'Chrome PDF Viewer',\n filename: 'internal-pdf-viewer',\n description: 'Portable Document Format',\n },\n {\n name: 'Native Client',\n filename: 'internal-nacl-plugin',\n description: '',\n },\n ];\n const arr: Record<string, unknown> = { length: plugins.length };\n for (let i = 0; i < plugins.length; i++) {\n arr[i] = plugins[i];\n }\n return arr;\n },\n configurable: true,\n });\n }\n\n // 5. Mask Chrome automation-related chrome.runtime detection\n // Pages can check if chrome.runtime.id exists to detect extensions\n try {\n const g = globalThis as Record<string, unknown>;\n const cr = g.chrome as Record<string, unknown> | undefined;\n if (cr && cr.runtime && (cr.runtime as Record<string, unknown>).id) {\n const origRuntime = cr.runtime as Record<string, unknown>;\n const handler: ProxyHandler<Record<string, unknown>> = {\n get(target, prop) {\n if (prop === 'id') {\n return undefined;\n }\n const value = Reflect.get(target, prop);\n return typeof value === 'function' ? value.bind(target) : value;\n },\n };\n g.chrome = new Proxy(cr, {\n get(target, prop) {\n if (prop === 'runtime') {\n return new Proxy(origRuntime, handler);\n }\n return Reflect.get(target, prop);\n },\n });\n }\n } catch {\n // chrome.runtime proxy may fail in some contexts — non-critical\n }\n\n // 6. Canvas fingerprint noise — deterministic per session\n (() => {\n const seed = (Math.random() * 0xffffffff) >>> 0;\n\n const xorshift32 = (state: number): number => {\n state ^= state << 13;\n state ^= state >>> 17;\n state ^= state << 5;\n return state >>> 0;\n };\n\n const noiseForPixel = (index: number): number => {\n const hash = xorshift32(seed ^ ((index * 2654435761) >>> 0));\n return (hash % 3) - 1;\n };\n\n const origGetImageData = CanvasRenderingContext2D.prototype.getImageData;\n CanvasRenderingContext2D.prototype.getImageData = function (\n ...args: [number, number, number, number, ...unknown[]]\n ) {\n const imageData = origGetImageData.apply(this, args as Parameters<typeof origGetImageData>);\n const { data } = imageData;\n for (let i = 0; i < data.length; i += 64) {\n const n = noiseForPixel(i >>> 2);\n data[i] = Math.max(0, Math.min(255, data[i] + n));\n data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + n));\n }\n return imageData;\n };\n\n const origToDataURL = HTMLCanvasElement.prototype.toDataURL;\n HTMLCanvasElement.prototype.toDataURL = function (...args: [string?, number?]) {\n try {\n const ctx = this.getContext('2d');\n if (ctx) {\n const img = ctx.getImageData(0, 0, this.width, this.height);\n ctx.putImageData(img, 0, 0);\n }\n } catch {\n // WebGL canvas or tainted canvas — skip noise\n }\n return origToDataURL.apply(this, args as Parameters<typeof origToDataURL>);\n };\n\n const origToBlob = HTMLCanvasElement.prototype.toBlob;\n HTMLCanvasElement.prototype.toBlob = function (callback: BlobCallback, ...rest: [string?, number?]) {\n try {\n const ctx = this.getContext('2d');\n if (ctx) {\n const img = ctx.getImageData(0, 0, this.width, this.height);\n ctx.putImageData(img, 0, 0);\n }\n } catch {\n // WebGL canvas or tainted canvas — skip noise\n }\n return origToBlob.call(\n this,\n callback,\n ...(rest as Parameters<typeof origToBlob> extends [BlobCallback, ...infer R] ? R : []),\n );\n };\n })();\n\n // 7. WebGL fingerprint masking — realistic renderer/vendor strings\n (() => {\n const SPOOFED_VENDOR = 'Google Inc. (NVIDIA)';\n const SPOOFED_RENDERER = 'ANGLE (NVIDIA, NVIDIA GeForce GTX 1650 Direct3D11 vs_5_0 ps_5_0, D3D11)';\n const UNMASKED_VENDOR = 0x9245;\n const UNMASKED_RENDERER = 0x9246;\n\n const patchGetParameter = (proto: { getParameter: (pname: number) => unknown }) => {\n const original = proto.getParameter;\n proto.getParameter = function (pname: number) {\n if (pname === UNMASKED_VENDOR) return SPOOFED_VENDOR;\n if (pname === UNMASKED_RENDERER) return SPOOFED_RENDERER;\n return original.call(this, pname);\n };\n };\n\n if (typeof WebGLRenderingContext !== 'undefined') {\n patchGetParameter(WebGLRenderingContext.prototype);\n }\n if (typeof WebGL2RenderingContext !== 'undefined') {\n patchGetParameter(WebGL2RenderingContext.prototype);\n }\n })();\n };\n\n const script = document.createElement('script');\n script.textContent = `(${overrides.toString()})();`;\n (document.documentElement || document.head || document.body).appendChild(script);\n script.remove();\n}\n","/**\n * Content Script - DOM Interaction Layer\n *\n * Runs in the context of web pages and provides DOM manipulation\n * capabilities for browser automation tools.\n *\n * NOTE: This file must be self-contained (no imports from shared modules)\n * because Chrome content scripts cannot use ES modules.\n */\n\nimport { buildAccessibilityTree } from './accessibility-tree.js';\nimport { type ElementLocator, getAccessibleName, getRole, locateElement } from './element-locator.js';\nimport { installStealthOverrides } from './stealth.js';\n\ninstallStealthOverrides();\n\n/**\n * Content action constants - inlined to avoid shared module imports\n */\nconst ContentAction = {\n CLICK: 'click',\n FILL: 'fill',\n TYPE: 'type',\n GET_SNAPSHOT: 'getSnapshot',\n EVALUATE_SCRIPT: 'evaluateScript',\n GET_ELEMENT_INFO: 'getElementInfo',\n GET_LOCATOR_CANDIDATES: 'getLocatorCandidates',\n HOVER: 'hover',\n SELECT: 'select',\n DRAG: 'drag',\n PRESS_KEY: 'pressKey',\n WAIT_FOR: 'waitFor',\n PREPARE_FOR_INPUT: 'prepareForInput',\n} as const;\n\nconst DEFAULT_TOOL_TIMEOUT_MS = 180_000;\n\ntype ContentActionType = (typeof ContentAction)[keyof typeof ContentAction];\n\ninterface ContentMessage {\n action: ContentActionType;\n params: Record<string, unknown>;\n}\n\ninterface TelemetryContext {\n traceId?: string;\n spanId?: string;\n}\n\ninterface ContentResponse {\n success: boolean;\n result?: unknown;\n error?: string;\n}\n\nconst VALID_ACTIONS = new Set(Object.values(ContentAction));\n\nfunction installConsoleMonitor(): void {\n const marker = '__browseToolConsoleMonitorInjectorInstalled__';\n if ((globalThis as Record<string, unknown>)[marker]) {\n return;\n }\n (globalThis as Record<string, unknown>)[marker] = true;\n\n const installer = () => {\n const runtime = window as typeof window & {\n __browseToolConsoleMonitor?: {\n messageCounter: number;\n messages: Array<{\n id: string;\n type: string;\n text: string;\n location?: { url: string; lineNumber: number; columnNumber: number };\n timestamp: string;\n }>;\n };\n __browseToolConsoleMonitorInstalled__?: boolean;\n };\n\n if (runtime.__browseToolConsoleMonitorInstalled__) {\n return;\n }\n runtime.__browseToolConsoleMonitorInstalled__ = true;\n\n if (!runtime.__browseToolConsoleMonitor) {\n runtime.__browseToolConsoleMonitor = { messageCounter: 0, messages: [] };\n }\n const state = runtime.__browseToolConsoleMonitor;\n\n const MAX_MESSAGES = 200;\n const consoleMethods = ['log', 'info', 'warn', 'error', 'debug', 'trace'] as const;\n\n const stringifyArg = (value: unknown): string => {\n if (typeof value === 'string') {\n return value;\n }\n if (value instanceof Error) {\n return value.stack || value.message;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n };\n\n for (const method of consoleMethods) {\n const original = console[method].bind(console);\n console[method] = (...args: unknown[]) => {\n const text = args.map((arg) => stringifyArg(arg)).join(' ');\n state.messages.push({\n id: `msg-${++state.messageCounter}`,\n type: method === 'warn' ? 'warning' : method,\n text,\n location: {\n url: window.location.href,\n lineNumber: 0,\n columnNumber: 0,\n },\n timestamp: new Date().toISOString(),\n });\n if (state.messages.length > MAX_MESSAGES) {\n state.messages.splice(0, state.messages.length - MAX_MESSAGES);\n }\n return original(...args);\n };\n }\n };\n\n const script = document.createElement('script');\n script.textContent = `(${installer.toString()})();`;\n (document.documentElement || document.head || document.body).appendChild(script);\n script.remove();\n}\n\nfunction extractTelemetryContext(params: Record<string, unknown>): TelemetryContext | undefined {\n const telemetry = params.__browseToolTelemetry;\n if (!telemetry || typeof telemetry !== 'object') {\n return undefined;\n }\n\n const traceId =\n typeof (telemetry as { traceId?: unknown }).traceId === 'string'\n ? (telemetry as { traceId: string }).traceId\n : undefined;\n const spanId =\n typeof (telemetry as { spanId?: unknown }).spanId === 'string'\n ? (telemetry as { spanId: string }).spanId\n : undefined;\n\n if (!traceId || !spanId) {\n return undefined;\n }\n\n return { traceId, spanId };\n}\n\nasync function emitTelemetry(\n level: 'debug' | 'error',\n message: string,\n action: ContentActionType,\n telemetryContext?: TelemetryContext,\n): Promise<void> {\n try {\n await chrome.runtime.sendMessage({\n type: 'BROWSER_TELEMETRY_EVENT',\n level,\n message,\n context: telemetryContext,\n attributes: {\n 'browse_tool.content.action': action,\n 'browse_tool.page.url': location.href,\n },\n });\n } catch {\n // Ignore background messaging failures.\n }\n}\n\nfunction validateMessage(message: unknown): ContentMessage | null {\n if (!message || typeof message !== 'object') return null;\n const msg = message as Record<string, unknown>;\n if (typeof msg.action !== 'string' || !VALID_ACTIONS.has(msg.action as ContentActionType)) return null;\n if (msg.params !== undefined && (typeof msg.params !== 'object' || msg.params === null)) return null;\n return {\n action: msg.action as ContentActionType,\n params: (msg.params as Record<string, unknown>) || {},\n };\n}\n\nchrome.runtime.onMessage.addListener(\n (message: unknown, _sender: chrome.runtime.MessageSender, sendResponse: (response: ContentResponse) => void) => {\n const validated = validateMessage(message);\n if (!validated) {\n sendResponse({\n success: false,\n error: 'Invalid message format: missing or invalid action',\n });\n return true;\n }\n\n const telemetryContext = extractTelemetryContext(validated.params);\n void emitTelemetry('debug', 'content action received', validated.action, telemetryContext);\n\n handleContentAction(validated)\n .then((result) => {\n void emitTelemetry('debug', 'content action completed', validated.action, telemetryContext);\n sendResponse({ success: true, result });\n })\n .catch((error: Error) => {\n void emitTelemetry('error', error.message, validated.action, telemetryContext);\n sendResponse({ success: false, error: error.message });\n });\n return true; // Async response\n },\n);\n\ninstallConsoleMonitor();\n\nasync function handleContentAction(message: ContentMessage): Promise<unknown> {\n const { action, params } = message;\n\n switch (action) {\n case ContentAction.CLICK:\n return handleClick(params);\n case ContentAction.FILL:\n return handleFill(params);\n case ContentAction.TYPE:\n return handleType(params);\n case ContentAction.GET_SNAPSHOT:\n return buildAccessibilityTree(typeof params.root === 'string' ? params.root : undefined);\n case ContentAction.EVALUATE_SCRIPT:\n return handleEvaluateScript(params);\n case ContentAction.GET_ELEMENT_INFO:\n return handleGetElementInfo(params);\n case ContentAction.GET_LOCATOR_CANDIDATES:\n return handleGetLocatorCandidates(params);\n case ContentAction.HOVER:\n return handleHover(params);\n case ContentAction.SELECT:\n return handleSelect(params);\n case ContentAction.DRAG:\n return handleDrag(params);\n case ContentAction.PRESS_KEY:\n return handlePressKey(params);\n case ContentAction.WAIT_FOR:\n return handleWaitFor(params);\n case ContentAction.PREPARE_FOR_INPUT:\n return handlePrepareForInput(params);\n }\n}\n\nasync function handleClick(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n // Scroll element into view\n element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n\n // Simulate mouse events for realistic click\n const rect = element.getBoundingClientRect();\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n\n element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: x, clientY: y }));\n}\n\nasync function handleFill(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const value = params.value as string;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (!(element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)) {\n throw new Error('Element is not an input or textarea');\n }\n\n // Focus and clear\n element.focus();\n element.value = '';\n\n // Set value and dispatch events\n element.value = value;\n element.dispatchEvent(new Event('input', { bubbles: true }));\n element.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nasync function handleType(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const text = params.text as string;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (element instanceof HTMLElement) {\n element.focus();\n }\n\n // Type character by character\n for (const char of text) {\n element.dispatchEvent(new KeyboardEvent('keydown', { key: char, bubbles: true }));\n element.dispatchEvent(new KeyboardEvent('keypress', { key: char, bubbles: true }));\n\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n element.value += char;\n element.dispatchEvent(new Event('input', { bubbles: true }));\n }\n\n element.dispatchEvent(new KeyboardEvent('keyup', { key: char, bubbles: true }));\n }\n}\n\nasync function handleEvaluateScript(params: Record<string, unknown>): Promise<unknown> {\n const script = params.script as string;\n try {\n // biome-ignore lint/complexity/noCommaOperator lint/security/noGlobalEval: indirect eval is required for content script execution in extension context\n return await Promise.resolve((0, eval)(script));\n } catch (error) {\n throw new Error(error instanceof Error ? error.message : 'Script execution failed', {\n cause: error,\n });\n }\n}\n\nasync function handleGetElementInfo(params: Record<string, unknown>): Promise<unknown> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n return {\n matched: false,\n matchCount: 0,\n element: null,\n };\n }\n\n const rect = element.getBoundingClientRect();\n return {\n matched: true,\n matchCount: 1,\n element: {\n tagName: element.tagName.toLowerCase(),\n id: element.id,\n className: element.getAttribute('class') || '',\n role: getRole(element),\n accessibleName: getAccessibleName(element),\n label:\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ? (element.labels?.[0]?.textContent?.replace(/\\s+/g, ' ').trim() ?? null)\n : null,\n placeholder: element.getAttribute('placeholder'),\n testId: element.getAttribute('data-testid') || element.getAttribute('data-test-id'),\n textContent: element.textContent?.replace(/\\s+/g, ' ').trim().substring(0, 500) || '',\n value:\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ? element.value\n : null,\n visible: rect.width > 0 && rect.height > 0,\n enabled: !(\n element instanceof HTMLButtonElement ||\n element instanceof HTMLInputElement ||\n element instanceof HTMLSelectElement ||\n element instanceof HTMLTextAreaElement\n )\n ? true\n : !element.disabled,\n rect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n },\n };\n}\n\nasync function handleGetLocatorCandidates(params: Record<string, unknown>): Promise<unknown> {\n const locator = params as ElementLocator;\n const limit = typeof params.limit === 'number' ? Math.max(1, Math.min(10, params.limit)) : 5;\n const normalizeText = (value: string | null | undefined): string => (value ?? '').replace(/\\s+/g, ' ').trim();\n const matchesText = (actual: string | null | undefined, expected: string | undefined, exact = false): boolean => {\n if (!expected) {\n return false;\n }\n const normalizedActual = normalizeText(actual);\n const normalizedExpected = normalizeText(expected);\n if (!normalizedActual || !normalizedExpected) {\n return false;\n }\n return exact\n ? normalizedActual === normalizedExpected\n : normalizedActual.toLowerCase().includes(normalizedExpected.toLowerCase());\n };\n const getLabelText = (element: Element): string | null => {\n if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n return element.labels?.[0]?.textContent ? normalizeText(element.labels[0].textContent) : null;\n }\n const wrappedLabel = element.closest('label');\n return wrappedLabel?.textContent ? normalizeText(wrappedLabel.textContent) : null;\n };\n\n const SKIP_TAGS = new Set(['html', 'body', 'head', 'script', 'style', 'noscript', 'template', 'meta', 'link']);\n const candidates = Array.from(document.querySelectorAll('*'))\n .map((element) => {\n if (SKIP_TAGS.has(element.tagName.toLowerCase())) return null;\n const accessibleName = getAccessibleName(element);\n const label = getLabelText(element);\n const placeholder = element.getAttribute('placeholder');\n const textContent = normalizeText(element.textContent);\n const role = getRole(element);\n const testId = element.getAttribute('data-testid') || element.getAttribute('data-test-id');\n const rect = element.getBoundingClientRect();\n const visible = rect.width > 0 && rect.height > 0;\n const enabled =\n !(\n element instanceof HTMLButtonElement ||\n element instanceof HTMLInputElement ||\n element instanceof HTMLSelectElement ||\n element instanceof HTMLTextAreaElement\n ) || !element.disabled;\n const reasons: string[] = [];\n let score = 0;\n let semanticSignals = 0;\n const exact = locator.exact ?? false;\n const isInteractive =\n role !== 'none' ||\n element instanceof HTMLButtonElement ||\n element instanceof HTMLInputElement ||\n element instanceof HTMLSelectElement ||\n element instanceof HTMLTextAreaElement ||\n (element instanceof HTMLAnchorElement && element.hasAttribute('href'));\n\n if (locator.role && role === locator.role) {\n score += 30;\n semanticSignals += 1;\n reasons.push('role match');\n }\n if (locator.name) {\n if (matchesText(accessibleName, locator.name, true)) {\n score += 60;\n semanticSignals += 1;\n reasons.push('exact accessible name match');\n } else if (matchesText(accessibleName, locator.name, exact)) {\n score += 35;\n semanticSignals += 1;\n reasons.push('accessible name match');\n }\n }\n if (locator.label) {\n if (matchesText(label, locator.label, true)) {\n score += 55;\n semanticSignals += 1;\n reasons.push('exact label match');\n } else if (matchesText(label, locator.label, exact)) {\n score += 30;\n semanticSignals += 1;\n reasons.push('label match');\n }\n }\n if (locator.placeholder && matchesText(placeholder, locator.placeholder, exact)) {\n score += 25;\n semanticSignals += 1;\n reasons.push('placeholder match');\n }\n if (locator.text && matchesText(textContent, locator.text, exact)) {\n score += 20;\n semanticSignals += 1;\n reasons.push('text match');\n }\n if (locator.testId && testId === locator.testId) {\n score += 50;\n semanticSignals += 1;\n reasons.push('test id match');\n }\n if (isInteractive) {\n score += 8;\n reasons.push('interactive element');\n }\n if (visible) {\n score += 10;\n reasons.push('visible');\n }\n if (enabled) {\n score += 5;\n reasons.push('enabled');\n }\n if (semanticSignals === 0) {\n return null;\n }\n\n return {\n score,\n reasons,\n candidate: {\n tagName: element.tagName.toLowerCase(),\n id: element.id,\n className: element.getAttribute('class') || '',\n role,\n accessibleName,\n label,\n placeholder,\n testId,\n textContent: textContent.slice(0, 500),\n visible,\n enabled,\n rect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n },\n };\n })\n .filter((entry): entry is NonNullable<typeof entry> => entry !== null && entry.score > 0)\n .sort((left, right) => right.score - left.score)\n .slice(0, limit);\n\n return {\n totalCandidates: candidates.length,\n candidates,\n };\n}\n\nasync function handleHover(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n\n const rect = element.getBoundingClientRect();\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n\n element.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, clientX: x, clientY: y }));\n}\n\nasync function handleSelect(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const value = params.value as string | string[];\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (!(element instanceof HTMLSelectElement)) {\n throw new Error('Element is not a select element');\n }\n\n const values = Array.isArray(value) ? value : [value];\n\n for (const option of element.options) {\n option.selected = values.includes(option.value) || values.includes(option.text);\n }\n\n element.dispatchEvent(new Event('input', { bubbles: true }));\n element.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nasync function handleDrag(params: Record<string, unknown>): Promise<void> {\n const sourceLocator = params.source as ElementLocator;\n const targetLocator = params.target as ElementLocator;\n\n const sourceElement = await locateElement(sourceLocator);\n const targetElement = await locateElement(targetLocator);\n\n if (!sourceElement) {\n throw new Error('Source element not found');\n }\n\n if (!targetElement) {\n throw new Error('Target element not found');\n }\n\n const sourceRect = sourceElement.getBoundingClientRect();\n const targetRect = targetElement.getBoundingClientRect();\n\n const sourceX = sourceRect.left + sourceRect.width / 2;\n const sourceY = sourceRect.top + sourceRect.height / 2;\n const targetX = targetRect.left + targetRect.width / 2;\n const targetY = targetRect.top + targetRect.height / 2;\n const dataTransfer = new DataTransfer();\n\n sourceElement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: sourceX, clientY: sourceY }));\n sourceElement.dispatchEvent(\n new DragEvent('dragstart', {\n bubbles: true,\n clientX: sourceX,\n clientY: sourceY,\n dataTransfer,\n }),\n );\n\n targetElement.dispatchEvent(\n new DragEvent('dragenter', {\n bubbles: true,\n clientX: targetX,\n clientY: targetY,\n dataTransfer,\n }),\n );\n targetElement.dispatchEvent(\n new DragEvent('dragover', {\n bubbles: true,\n clientX: targetX,\n clientY: targetY,\n dataTransfer,\n }),\n );\n targetElement.dispatchEvent(\n new DragEvent('drop', {\n bubbles: true,\n clientX: targetX,\n clientY: targetY,\n dataTransfer,\n }),\n );\n\n sourceElement.dispatchEvent(\n new DragEvent('dragend', {\n bubbles: true,\n clientX: targetX,\n clientY: targetY,\n dataTransfer,\n }),\n );\n targetElement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: targetX, clientY: targetY }));\n}\n\nasync function handlePressKey(params: Record<string, unknown>): Promise<void> {\n const key = params.key as string;\n const modifiers = params.modifiers as string[] | undefined;\n\n const eventInit: KeyboardEventInit = {\n key,\n bubbles: true,\n ctrlKey: modifiers?.includes('Control') || modifiers?.includes('Ctrl'),\n shiftKey: modifiers?.includes('Shift'),\n altKey: modifiers?.includes('Alt'),\n metaKey: modifiers?.includes('Meta') || modifiers?.includes('Command'),\n };\n\n const activeElement = document.activeElement || document.body;\n activeElement.dispatchEvent(new KeyboardEvent('keydown', eventInit));\n activeElement.dispatchEvent(new KeyboardEvent('keypress', eventInit));\n activeElement.dispatchEvent(new KeyboardEvent('keyup', eventInit));\n}\n\nasync function handleWaitFor(params: Record<string, unknown>): Promise<void> {\n const selector = params.selector as string | undefined;\n const text = params.text as string | undefined;\n const state = (params.state as string) || 'visible';\n const timeout = (params.timeout as number) || DEFAULT_TOOL_TIMEOUT_MS;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeout) {\n if (selector) {\n const element = await locateElement({ selector });\n if (state === 'visible' && element && isVisible(element)) {\n return;\n }\n if (state === 'hidden' && (!element || !isVisible(element))) {\n return;\n }\n if (state === 'attached' && element) {\n return;\n }\n if (state === 'detached' && !element) {\n return;\n }\n }\n\n if (text) {\n const found = document.body.textContent?.includes(text);\n if (found) {\n return;\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n throw new Error(`Wait condition not met within ${timeout}ms`);\n}\n\nasync function handlePrepareForInput(params: Record<string, unknown>): Promise<unknown> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n element.scrollIntoView({ behavior: 'instant', block: 'center' });\n\n await new Promise((resolve) => setTimeout(resolve, 50));\n\n const rect = element.getBoundingClientRect();\n\n return {\n rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },\n tagName: element.tagName.toLowerCase(),\n isFocusable:\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement ||\n element.hasAttribute('contenteditable') ||\n element.getAttribute('tabindex') !== null,\n };\n}\n\nfunction isVisible(element: Element): boolean {\n const style = window.getComputedStyle(element);\n return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"content.js","names":[],"sources":["../../src/extension/content/element-locator.ts","../../src/extension/content/accessibility-tree.ts","../../src/extension/content/stealth.ts","../../src/extension/content/index.ts"],"sourcesContent":["/**\n * Element Locator - Strategies for finding elements in the DOM\n *\n * Supports multiple location strategies:\n * - CSS selector\n * - XPath\n * - Text content\n * - Accessibility UID (from snapshot)\n */\n\nexport interface ElementLocator {\n uid?: string;\n role?: string;\n name?: string;\n label?: string;\n placeholder?: string;\n text?: string;\n exact?: boolean;\n selector?: string;\n xpath?: string;\n testId?: string;\n}\n\nconst uidToElement = new Map<string, WeakRef<Element>>();\nlet uidCounter = 0;\n\ninterface SelectorShortcut {\n kind: 'text' | 'hasText';\n text: string;\n tagName?: string;\n exact: boolean;\n}\n\nexport function assignUid(element: Element): string {\n const uid = `e${++uidCounter}`;\n uidToElement.set(uid, new WeakRef(element));\n return uid;\n}\n\nexport function getElementByUid(uid: string): Element | null {\n const ref = uidToElement.get(uid);\n return ref?.deref() || null;\n}\n\nexport function clearUidMap(): void {\n uidToElement.clear();\n uidCounter = 0;\n}\n\nfunction normalizeText(value: string | null | undefined): string {\n return (value ?? '').replace(/\\s+/g, ' ').trim();\n}\n\nfunction matchesText(actual: string | null | undefined, expected: string, exact = false): boolean {\n const normalizedActual = normalizeText(actual);\n const normalizedExpected = normalizeText(expected);\n\n if (!normalizedActual || !normalizedExpected) {\n return false;\n }\n\n if (exact) {\n return normalizedActual === normalizedExpected;\n }\n\n return normalizedActual.toLowerCase().includes(normalizedExpected.toLowerCase());\n}\n\nfunction unquoteSelectorText(rawText: string): { text: string; exact: boolean } {\n const text = rawText.trim();\n const quote = text[0];\n if ((quote === '\"' || quote === \"'\") && text.endsWith(quote)) {\n return { text: text.slice(1, -1), exact: true };\n }\n return { text, exact: false };\n}\n\nfunction parseSelectorShortcut(selector: string): SelectorShortcut | null {\n const trimmed = selector.trim();\n\n if (trimmed.startsWith('text=')) {\n const parsed = unquoteSelectorText(trimmed.slice('text='.length));\n return { kind: 'text', text: parsed.text, exact: parsed.exact };\n }\n\n const hasTextMatch = trimmed.match(/^([a-zA-Z][\\w-]*)?:has-text\\((.*)\\)$/);\n if (hasTextMatch) {\n const parsed = unquoteSelectorText(hasTextMatch[2] ?? '');\n return {\n kind: 'hasText',\n tagName: hasTextMatch[1]?.toLowerCase(),\n text: parsed.text,\n exact: false,\n };\n }\n\n return null;\n}\n\nfunction formatUnsupportedSelectorError(selector: string, error: unknown): Error {\n const reason = error instanceof Error ? error.message : String(error);\n return new Error(\n `Unsupported CSS selector \"${selector}\": ${reason}. If you meant Playwright syntax, use text/name/role fields instead. Supported selector shortcuts are text=... and tag:has-text(\"...\").`,\n );\n}\n\nfunction getAssociatedControl(label: HTMLLabelElement): Element | null {\n if (label.control) {\n return label.control;\n }\n\n const forAttr = label.getAttribute('for');\n if (forAttr) {\n const target = document.getElementById(forAttr);\n if (target) {\n return target;\n }\n }\n\n return label.querySelector('input,select,textarea,button');\n}\n\n// NOTE: getRole / getAccessibleName are importable by content-script code.\n// For executeScript / page.evaluate callbacks, functions must be self-contained\n// (no imports). Keep those copies in sync with the canonical versions here.\n\nexport function getAccessibleName(element: Element): string {\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) {\n return normalizeText(ariaLabel);\n }\n\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const labels = labelledBy\n .split(/\\s+/)\n .map((id) => normalizeText(document.getElementById(id)?.textContent))\n .filter(Boolean);\n if (labels.length > 0) {\n return labels.join(' ');\n }\n }\n\n if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n if (element.id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(element.id)}\"]`);\n if (label?.textContent) {\n return normalizeText(label.textContent);\n }\n }\n if (element.placeholder) {\n return normalizeText(element.placeholder);\n }\n }\n\n const label = element.closest('label');\n if (label?.textContent) {\n return normalizeText(label.textContent);\n }\n\n if (element instanceof HTMLImageElement && element.alt) {\n return normalizeText(element.alt);\n }\n\n if (element.textContent) {\n return normalizeText(element.textContent);\n }\n\n return '';\n}\n\nexport function getRole(element: Element): string {\n const ariaRole = element.getAttribute('role');\n if (ariaRole) {\n return ariaRole;\n }\n\n if (element instanceof HTMLInputElement) {\n const type = (element.type || 'text').toLowerCase();\n const inputRoles: Record<string, string> = {\n button: 'button',\n checkbox: 'checkbox',\n email: 'textbox',\n number: 'spinbutton',\n password: 'textbox',\n radio: 'radio',\n range: 'slider',\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 tagName = element.tagName.toLowerCase();\n const roleMap: Record<string, string> = {\n a: element.hasAttribute('href') ? 'link' : 'none',\n article: 'article',\n aside: 'complementary',\n button: 'button',\n footer: 'contentinfo',\n form: 'form',\n h1: 'heading',\n h2: 'heading',\n h3: 'heading',\n h4: 'heading',\n h5: 'heading',\n h6: 'heading',\n header: 'banner',\n img: 'img',\n li: 'listitem',\n main: 'main',\n nav: 'navigation',\n ol: 'list',\n option: 'option',\n progress: 'progressbar',\n section: element.hasAttribute('aria-label') ? 'region' : 'none',\n select: 'combobox',\n table: 'table',\n td: 'cell',\n textarea: 'textbox',\n th: 'columnheader',\n tr: 'row',\n ul: 'list',\n };\n\n return roleMap[tagName] || 'none';\n}\n\nfunction allElements(): Element[] {\n return Array.from(document.querySelectorAll('*'));\n}\n\nfunction findByRole(locator: ElementLocator): Element | null {\n if (!locator.role) {\n return null;\n }\n\n const candidates = allElements().filter((element) => getRole(element) === locator.role);\n if (!locator.name) {\n return candidates[0] ?? null;\n }\n\n return candidates.find((element) => matchesText(getAccessibleName(element), locator.name!, locator.exact)) ?? null;\n}\n\nfunction findByLabel(locator: ElementLocator): Element | null {\n if (!locator.label) {\n return null;\n }\n\n const labels = Array.from(document.querySelectorAll('label')).filter((label) =>\n matchesText(label.textContent, locator.label!, locator.exact),\n );\n\n for (const label of labels) {\n const control = getAssociatedControl(label as HTMLLabelElement);\n if (control) {\n return control;\n }\n }\n\n return labels[0] ?? null;\n}\n\nfunction findByPlaceholder(locator: ElementLocator): Element | null {\n if (!locator.placeholder) {\n return null;\n }\n\n return (\n allElements().find((element) => {\n const placeholder = element.getAttribute('placeholder');\n return matchesText(placeholder, locator.placeholder!, locator.exact);\n }) ?? null\n );\n}\n\nfunction findByText(locator: ElementLocator): Element | null {\n if (!locator.text) {\n return null;\n }\n\n const candidates = allElements().filter((element) => matchesText(element.textContent, locator.text!, locator.exact));\n if (candidates.length === 0) {\n return null;\n }\n\n for (const candidate of candidates) {\n if (candidate instanceof HTMLLabelElement) {\n const control = getAssociatedControl(candidate);\n if (control) {\n return control;\n }\n }\n }\n\n return candidates[0];\n}\n\nfunction findByTestId(locator: ElementLocator): Element | null {\n if (!locator.testId) {\n return null;\n }\n\n return document.querySelector(`[data-testid=\"${CSS.escape(locator.testId)}\"]`);\n}\n\nfunction findBySelectorShortcut(shortcut: SelectorShortcut): Element | null {\n if (shortcut.kind === 'text') {\n return findByText({ text: shortcut.text, exact: shortcut.exact });\n }\n\n const elements = shortcut.tagName\n ? allElements().filter((element) => element.tagName.toLowerCase() === shortcut.tagName)\n : allElements();\n return elements.find((element) => matchesText(element.textContent, shortcut.text)) ?? null;\n}\n\nexport async function locateElement(locator: ElementLocator): Promise<Element | null> {\n // Try UID first (most precise)\n if (locator.uid) {\n const element = getElementByUid(locator.uid);\n if (element) return element;\n }\n\n // Try semantic selectors before raw DOM selectors.\n const semanticMatches = [\n findByRole(locator),\n findByLabel(locator),\n findByPlaceholder(locator),\n findByText(locator),\n findByTestId(locator),\n ];\n for (const element of semanticMatches) {\n if (element) {\n return element;\n }\n }\n\n // Try CSS selector\n if (locator.selector) {\n if (/^uid=/.test(locator.selector.trim())) {\n throw new Error(\n `UID selectors must use the uid field, for example {\"uid\":\"${locator.selector.trim().slice(4)}\"}. Snapshot UIDs are temporary, so take a new snapshot before retrying if it no longer resolves.`,\n );\n }\n const shortcut = parseSelectorShortcut(locator.selector);\n if (shortcut) {\n const element = findBySelectorShortcut(shortcut);\n if (element) return element;\n } else {\n try {\n const element = document.querySelector(locator.selector);\n if (element) return element;\n } catch (error) {\n throw formatUnsupportedSelectorError(locator.selector, error);\n }\n }\n }\n\n // Try XPath\n if (locator.xpath) {\n const result = document.evaluate(locator.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);\n if (result.singleNodeValue instanceof Element) {\n return result.singleNodeValue;\n }\n }\n\n // Try explicit accessible name lookup if a name is provided without role.\n if (locator.name) {\n const element = allElements().find((candidate) =>\n matchesText(getAccessibleName(candidate), locator.name!, locator.exact),\n );\n if (element) {\n return element;\n }\n }\n\n return null;\n}\n","/**\n * Accessibility Tree Builder\n *\n * Generates an accessibility snapshot of the page,\n * similar to Playwright's accessibility tree format.\n */\n\nimport { assignUid, clearUidMap } from './element-locator.js';\n\nexport interface AccessibilityNode {\n uid: string;\n role: string;\n name?: string;\n value?: string;\n description?: string;\n children?: AccessibilityNode[];\n focused?: boolean;\n disabled?: boolean;\n checked?: boolean | 'mixed';\n selected?: boolean;\n expanded?: boolean;\n level?: number;\n pressed?: boolean | 'mixed';\n}\n\nexport function buildAccessibilityTree(rootSelector?: string): AccessibilityNode {\n // Clear previous UID assignments\n clearUidMap();\n\n const rootElement = rootSelector ? (document.querySelector(rootSelector) ?? document.body) : document.body;\n const root = buildNode(rootElement as Element, 0);\n return root || { uid: 'root', role: 'none', name: 'Empty page' };\n}\n\nfunction buildNode(element: Element, depth: number): AccessibilityNode | null {\n // Skip hidden elements\n const style = getComputedStyle(element);\n if (style.display === 'none' || style.visibility === 'hidden') {\n return null;\n }\n\n const role = getRole(element);\n const name = getAccessibleName(element);\n const uid = assignUid(element);\n\n // Build children\n const children: AccessibilityNode[] = [];\n for (const child of element.children) {\n const childNode = buildNode(child, depth + 1);\n if (childNode) {\n children.push(childNode);\n }\n }\n\n // Skip non-semantic containers with no accessible name\n if (role === 'none' && !name && children.length === 1) {\n return children[0];\n }\n\n const node: AccessibilityNode = {\n uid,\n role,\n };\n\n if (name) node.name = name;\n if (children.length > 0) node.children = children;\n\n // Add state properties\n addStateProperties(element, node);\n\n return node;\n}\n\nfunction getRole(element: Element): string {\n // Explicit ARIA role\n const ariaRole = element.getAttribute('role');\n if (ariaRole) return ariaRole;\n\n // Implicit roles based on tag name\n const tagName = element.tagName.toLowerCase();\n const roleMap: Record<string, string> = {\n a: element.hasAttribute('href') ? 'link' : 'none',\n article: 'article',\n aside: 'complementary',\n button: 'button',\n footer: 'contentinfo',\n form: 'form',\n h1: 'heading',\n h2: 'heading',\n h3: 'heading',\n h4: 'heading',\n h5: 'heading',\n h6: 'heading',\n header: 'banner',\n img: 'img',\n input: getInputRole(element as HTMLInputElement),\n li: 'listitem',\n main: 'main',\n nav: 'navigation',\n ol: 'list',\n option: 'option',\n progress: 'progressbar',\n section: element.hasAttribute('aria-label') ? 'region' : 'none',\n select: 'combobox',\n table: 'table',\n tbody: 'rowgroup',\n td: 'cell',\n textarea: 'textbox',\n th: 'columnheader',\n tr: 'row',\n ul: 'list',\n };\n\n return roleMap[tagName] || 'none';\n}\n\nfunction getInputRole(input: HTMLInputElement): string {\n const type = (input.type || 'text').toLowerCase();\n const inputRoles: Record<string, string> = {\n button: 'button',\n checkbox: 'checkbox',\n email: 'textbox',\n number: 'spinbutton',\n password: 'textbox',\n radio: 'radio',\n range: 'slider',\n search: 'searchbox',\n submit: 'button',\n tel: 'textbox',\n text: 'textbox',\n url: 'textbox',\n };\n return inputRoles[type] || 'textbox';\n}\n\nfunction getAccessibleName(element: Element): string | undefined {\n // aria-label\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel;\n\n // aria-labelledby\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const labels = labelledBy\n .split(' ')\n .map((id) => document.getElementById(id)?.textContent)\n .filter(Boolean)\n .join(' ');\n if (labels) return labels;\n }\n\n // For inputs, check associated label\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n const id = element.id;\n if (id) {\n const label = document.querySelector(`label[for=\"${id}\"]`);\n if (label?.textContent) return label.textContent.trim();\n }\n }\n\n // Text content for certain elements\n const tagName = element.tagName.toLowerCase();\n if (['button', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'label', 'option'].includes(tagName)) {\n const text = element.textContent?.trim();\n if (text && text.length < 100) return text;\n }\n\n // Alt text for images\n if (element instanceof HTMLImageElement && element.alt) {\n return element.alt;\n }\n\n // Placeholder for inputs\n if (element instanceof HTMLInputElement && element.placeholder) {\n return element.placeholder;\n }\n\n return undefined;\n}\n\nfunction addStateProperties(element: Element, node: AccessibilityNode): void {\n // Focus state\n if (document.activeElement === element) {\n node.focused = true;\n }\n\n // Disabled state\n if ((element as HTMLInputElement).disabled) {\n node.disabled = true;\n }\n\n // Checked state\n if (element instanceof HTMLInputElement) {\n if (element.type === 'checkbox' || element.type === 'radio') {\n node.checked = element.indeterminate ? 'mixed' : element.checked;\n }\n }\n\n // Selected state\n if (element instanceof HTMLOptionElement) {\n node.selected = element.selected;\n }\n\n // Expanded state\n const ariaExpanded = element.getAttribute('aria-expanded');\n if (ariaExpanded) {\n node.expanded = ariaExpanded === 'true';\n }\n\n // Heading level\n const headingMatch = element.tagName.match(/^H([1-6])$/);\n if (headingMatch) {\n node.level = Number.parseInt(headingMatch[1], 10);\n }\n\n // Pressed state\n const ariaPressed = element.getAttribute('aria-pressed');\n if (ariaPressed) {\n node.pressed = ariaPressed === 'mixed' ? 'mixed' : ariaPressed === 'true';\n }\n}\n","/**\n * Stealth overrides injected into the MAIN world before page scripts run.\n * Masks automation signals that anti-bot systems (TikTok, etc.) detect.\n */\n\nexport function installStealthOverrides(): void {\n const marker = '__browseToolStealthInstalled__';\n if ((globalThis as Record<string, unknown>)[marker]) {\n return;\n }\n (globalThis as Record<string, unknown>)[marker] = true;\n\n const overrides = () => {\n const w = window as typeof window & { __browseToolStealthInstalled__?: boolean };\n if (w.__browseToolStealthInstalled__) {\n return;\n }\n w.__browseToolStealthInstalled__ = true;\n\n // 1. Mask navigator.webdriver\n Object.defineProperty(navigator, 'webdriver', {\n get: () => undefined,\n configurable: true,\n });\n\n // 2. Normalize navigator.hardwareConcurrency (Docker containers often expose 1-2 cores)\n if (navigator.hardwareConcurrency < 4) {\n Object.defineProperty(navigator, 'hardwareConcurrency', {\n get: () => 8,\n configurable: true,\n });\n }\n\n // 3. Override permissions.query to return \"prompt\" for notifications\n // Chrome for Testing defaults to \"denied\" which is a known fingerprint.\n const originalQuery = navigator.permissions.query.bind(navigator.permissions);\n navigator.permissions.query = (descriptor: PermissionDescriptor) => {\n if (descriptor.name === 'notifications') {\n return Promise.resolve({ state: 'prompt', onchange: null } as PermissionStatus);\n }\n return originalQuery(descriptor);\n };\n\n // 4. Spoof navigator.plugins with realistic entries (empty plugins = headless signal)\n const pluginCount = (navigator as { plugins: { length: number } }).plugins.length;\n if (pluginCount === 0) {\n Object.defineProperty(navigator, 'plugins', {\n get: () => {\n const plugins = [\n { name: 'PDF Viewer', filename: 'internal-pdf-viewer', description: 'Portable Document Format' },\n {\n name: 'Chrome PDF Plugin',\n filename: 'internal-pdf-viewer',\n description: 'Portable Document Format',\n },\n {\n name: 'Chrome PDF Viewer',\n filename: 'internal-pdf-viewer',\n description: 'Portable Document Format',\n },\n {\n name: 'Native Client',\n filename: 'internal-nacl-plugin',\n description: '',\n },\n ];\n const arr: Record<string, unknown> = { length: plugins.length };\n for (let i = 0; i < plugins.length; i++) {\n arr[i] = plugins[i];\n }\n return arr;\n },\n configurable: true,\n });\n }\n\n // 5. Mask Chrome automation-related chrome.runtime detection\n // Pages can check if chrome.runtime.id exists to detect extensions\n try {\n const g = globalThis as Record<string, unknown>;\n const cr = g.chrome as Record<string, unknown> | undefined;\n if (cr && cr.runtime && (cr.runtime as Record<string, unknown>).id) {\n const origRuntime = cr.runtime as Record<string, unknown>;\n const handler: ProxyHandler<Record<string, unknown>> = {\n get(target, prop) {\n if (prop === 'id') {\n return undefined;\n }\n const value = Reflect.get(target, prop);\n return typeof value === 'function' ? value.bind(target) : value;\n },\n };\n g.chrome = new Proxy(cr, {\n get(target, prop) {\n if (prop === 'runtime') {\n return new Proxy(origRuntime, handler);\n }\n return Reflect.get(target, prop);\n },\n });\n }\n } catch {\n // chrome.runtime proxy may fail in some contexts — non-critical\n }\n\n // 6. Canvas fingerprint noise — deterministic per session\n (() => {\n const seed = (Math.random() * 0xffffffff) >>> 0;\n\n const xorshift32 = (state: number): number => {\n state ^= state << 13;\n state ^= state >>> 17;\n state ^= state << 5;\n return state >>> 0;\n };\n\n const noiseForPixel = (index: number): number => {\n const hash = xorshift32(seed ^ ((index * 2654435761) >>> 0));\n return (hash % 3) - 1;\n };\n\n const origGetImageData = CanvasRenderingContext2D.prototype.getImageData;\n CanvasRenderingContext2D.prototype.getImageData = function (\n ...args: [number, number, number, number, ...unknown[]]\n ) {\n const imageData = origGetImageData.apply(this, args as Parameters<typeof origGetImageData>);\n const { data } = imageData;\n for (let i = 0; i < data.length; i += 64) {\n const n = noiseForPixel(i >>> 2);\n data[i] = Math.max(0, Math.min(255, data[i] + n));\n data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + n));\n }\n return imageData;\n };\n\n const origToDataURL = HTMLCanvasElement.prototype.toDataURL;\n HTMLCanvasElement.prototype.toDataURL = function (...args: [string?, number?]) {\n try {\n const ctx = this.getContext('2d');\n if (ctx) {\n const img = ctx.getImageData(0, 0, this.width, this.height);\n ctx.putImageData(img, 0, 0);\n }\n } catch {\n // WebGL canvas or tainted canvas — skip noise\n }\n return origToDataURL.apply(this, args as Parameters<typeof origToDataURL>);\n };\n\n const origToBlob = HTMLCanvasElement.prototype.toBlob;\n HTMLCanvasElement.prototype.toBlob = function (callback: BlobCallback, ...rest: [string?, number?]) {\n try {\n const ctx = this.getContext('2d');\n if (ctx) {\n const img = ctx.getImageData(0, 0, this.width, this.height);\n ctx.putImageData(img, 0, 0);\n }\n } catch {\n // WebGL canvas or tainted canvas — skip noise\n }\n return origToBlob.call(\n this,\n callback,\n ...(rest as Parameters<typeof origToBlob> extends [BlobCallback, ...infer R] ? R : []),\n );\n };\n })();\n\n // 7. WebGL fingerprint masking — realistic renderer/vendor strings\n (() => {\n const SPOOFED_VENDOR = 'Google Inc. (NVIDIA)';\n const SPOOFED_RENDERER = 'ANGLE (NVIDIA, NVIDIA GeForce GTX 1650 Direct3D11 vs_5_0 ps_5_0, D3D11)';\n const UNMASKED_VENDOR = 0x9245;\n const UNMASKED_RENDERER = 0x9246;\n\n const patchGetParameter = (proto: { getParameter: (pname: number) => unknown }) => {\n const original = proto.getParameter;\n proto.getParameter = function (pname: number) {\n if (pname === UNMASKED_VENDOR) return SPOOFED_VENDOR;\n if (pname === UNMASKED_RENDERER) return SPOOFED_RENDERER;\n return original.call(this, pname);\n };\n };\n\n if (typeof WebGLRenderingContext !== 'undefined') {\n patchGetParameter(WebGLRenderingContext.prototype);\n }\n if (typeof WebGL2RenderingContext !== 'undefined') {\n patchGetParameter(WebGL2RenderingContext.prototype);\n }\n })();\n };\n\n const script = document.createElement('script');\n script.textContent = `(${overrides.toString()})();`;\n (document.documentElement || document.head || document.body).appendChild(script);\n script.remove();\n}\n","/**\n * Content Script - DOM Interaction Layer\n *\n * Runs in the context of web pages and provides DOM manipulation\n * capabilities for browser automation tools.\n *\n * NOTE: This file must be self-contained (no imports from shared modules)\n * because Chrome content scripts cannot use ES modules.\n */\n\nimport { buildAccessibilityTree } from './accessibility-tree.js';\nimport { type ElementLocator, getAccessibleName, getRole, locateElement } from './element-locator.js';\nimport { installStealthOverrides } from './stealth.js';\n\ninstallStealthOverrides();\n\n/**\n * Content action constants - inlined to avoid shared module imports\n */\nconst ContentAction = {\n CLICK: 'click',\n FILL: 'fill',\n TYPE: 'type',\n GET_SNAPSHOT: 'getSnapshot',\n EVALUATE_SCRIPT: 'evaluateScript',\n GET_ELEMENT_INFO: 'getElementInfo',\n GET_LOCATOR_CANDIDATES: 'getLocatorCandidates',\n HOVER: 'hover',\n SELECT: 'select',\n DRAG: 'drag',\n PRESS_KEY: 'pressKey',\n WAIT_FOR: 'waitFor',\n PREPARE_FOR_INPUT: 'prepareForInput',\n} as const;\n\nconst DEFAULT_TOOL_TIMEOUT_MS = 180_000;\n\ntype ContentActionType = (typeof ContentAction)[keyof typeof ContentAction];\n\ninterface ContentMessage {\n action: ContentActionType;\n params: Record<string, unknown>;\n}\n\ninterface TelemetryContext {\n traceId?: string;\n spanId?: string;\n}\n\ninterface ContentResponse {\n success: boolean;\n result?: unknown;\n error?: string;\n}\n\nconst VALID_ACTIONS = new Set(Object.values(ContentAction));\n\nfunction installConsoleMonitor(): void {\n const marker = '__browseToolConsoleMonitorInjectorInstalled__';\n if ((globalThis as Record<string, unknown>)[marker]) {\n return;\n }\n (globalThis as Record<string, unknown>)[marker] = true;\n\n const installer = () => {\n const runtime = window as typeof window & {\n __browseToolConsoleMonitor?: {\n messageCounter: number;\n messages: Array<{\n id: string;\n type: string;\n text: string;\n location?: { url: string; lineNumber: number; columnNumber: number };\n timestamp: string;\n }>;\n };\n __browseToolConsoleMonitorInstalled__?: boolean;\n };\n\n if (runtime.__browseToolConsoleMonitorInstalled__) {\n return;\n }\n runtime.__browseToolConsoleMonitorInstalled__ = true;\n\n if (!runtime.__browseToolConsoleMonitor) {\n runtime.__browseToolConsoleMonitor = { messageCounter: 0, messages: [] };\n }\n const state = runtime.__browseToolConsoleMonitor;\n\n const MAX_MESSAGES = 200;\n const consoleMethods = ['log', 'info', 'warn', 'error', 'debug', 'trace'] as const;\n\n const stringifyArg = (value: unknown): string => {\n if (typeof value === 'string') {\n return value;\n }\n if (value instanceof Error) {\n return value.stack || value.message;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n };\n\n for (const method of consoleMethods) {\n const original = console[method].bind(console);\n console[method] = (...args: unknown[]) => {\n const text = args.map((arg) => stringifyArg(arg)).join(' ');\n state.messages.push({\n id: `msg-${++state.messageCounter}`,\n type: method === 'warn' ? 'warning' : method,\n text,\n location: {\n url: window.location.href,\n lineNumber: 0,\n columnNumber: 0,\n },\n timestamp: new Date().toISOString(),\n });\n if (state.messages.length > MAX_MESSAGES) {\n state.messages.splice(0, state.messages.length - MAX_MESSAGES);\n }\n return original(...args);\n };\n }\n };\n\n const script = document.createElement('script');\n script.textContent = `(${installer.toString()})();`;\n (document.documentElement || document.head || document.body).appendChild(script);\n script.remove();\n}\n\nfunction extractTelemetryContext(params: Record<string, unknown>): TelemetryContext | undefined {\n const telemetry = params.__browseToolTelemetry;\n if (!telemetry || typeof telemetry !== 'object') {\n return undefined;\n }\n\n const traceId =\n typeof (telemetry as { traceId?: unknown }).traceId === 'string'\n ? (telemetry as { traceId: string }).traceId\n : undefined;\n const spanId =\n typeof (telemetry as { spanId?: unknown }).spanId === 'string'\n ? (telemetry as { spanId: string }).spanId\n : undefined;\n\n if (!traceId || !spanId) {\n return undefined;\n }\n\n return { traceId, spanId };\n}\n\nasync function emitTelemetry(\n level: 'debug' | 'error',\n message: string,\n action: ContentActionType,\n telemetryContext?: TelemetryContext,\n): Promise<void> {\n try {\n await chrome.runtime.sendMessage({\n type: 'BROWSER_TELEMETRY_EVENT',\n level,\n message,\n context: telemetryContext,\n attributes: {\n 'browse_tool.content.action': action,\n 'browse_tool.page.url': location.href,\n },\n });\n } catch {\n // Ignore background messaging failures.\n }\n}\n\nfunction validateMessage(message: unknown): ContentMessage | null {\n if (!message || typeof message !== 'object') return null;\n const msg = message as Record<string, unknown>;\n if (typeof msg.action !== 'string' || !VALID_ACTIONS.has(msg.action as ContentActionType)) return null;\n if (msg.params !== undefined && (typeof msg.params !== 'object' || msg.params === null)) return null;\n return {\n action: msg.action as ContentActionType,\n params: (msg.params as Record<string, unknown>) || {},\n };\n}\n\nchrome.runtime.onMessage.addListener(\n (message: unknown, _sender: chrome.runtime.MessageSender, sendResponse: (response: ContentResponse) => void) => {\n const validated = validateMessage(message);\n if (!validated) {\n sendResponse({\n success: false,\n error: 'Invalid message format: missing or invalid action',\n });\n return true;\n }\n\n const telemetryContext = extractTelemetryContext(validated.params);\n void emitTelemetry('debug', 'content action received', validated.action, telemetryContext);\n\n handleContentAction(validated)\n .then((result) => {\n void emitTelemetry('debug', 'content action completed', validated.action, telemetryContext);\n sendResponse({ success: true, result });\n })\n .catch((error: Error) => {\n void emitTelemetry('error', error.message, validated.action, telemetryContext);\n sendResponse({ success: false, error: error.message });\n });\n return true; // Async response\n },\n);\n\ninstallConsoleMonitor();\n\nasync function handleContentAction(message: ContentMessage): Promise<unknown> {\n const { action, params } = message;\n\n switch (action) {\n case ContentAction.CLICK:\n return handleClick(params);\n case ContentAction.FILL:\n return handleFill(params);\n case ContentAction.TYPE:\n return handleType(params);\n case ContentAction.GET_SNAPSHOT:\n return buildAccessibilityTree(typeof params.root === 'string' ? params.root : undefined);\n case ContentAction.EVALUATE_SCRIPT:\n return handleEvaluateScript(params);\n case ContentAction.GET_ELEMENT_INFO:\n return handleGetElementInfo(params);\n case ContentAction.GET_LOCATOR_CANDIDATES:\n return handleGetLocatorCandidates(params);\n case ContentAction.HOVER:\n return handleHover(params);\n case ContentAction.SELECT:\n return handleSelect(params);\n case ContentAction.DRAG:\n return handleDrag(params);\n case ContentAction.PRESS_KEY:\n return handlePressKey(params);\n case ContentAction.WAIT_FOR:\n return handleWaitFor(params);\n case ContentAction.PREPARE_FOR_INPUT:\n return handlePrepareForInput(params);\n }\n}\n\nasync function handleClick(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n // Scroll element into view\n element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n\n // Simulate mouse events for realistic click\n const rect = element.getBoundingClientRect();\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n\n element.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: x, clientY: y }));\n}\n\nasync function handleFill(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const value = params.value as string;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (!(element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)) {\n throw new Error('Element is not an input or textarea');\n }\n\n // Focus and clear\n element.focus();\n element.value = '';\n\n // Set value and dispatch events\n element.value = value;\n element.dispatchEvent(new Event('input', { bubbles: true }));\n element.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nasync function handleType(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const text = params.text as string;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (element instanceof HTMLElement) {\n element.focus();\n }\n\n // Type character by character\n for (const char of text) {\n element.dispatchEvent(new KeyboardEvent('keydown', { key: char, bubbles: true }));\n element.dispatchEvent(new KeyboardEvent('keypress', { key: char, bubbles: true }));\n\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n element.value += char;\n element.dispatchEvent(new Event('input', { bubbles: true }));\n }\n\n element.dispatchEvent(new KeyboardEvent('keyup', { key: char, bubbles: true }));\n }\n}\n\nasync function handleEvaluateScript(params: Record<string, unknown>): Promise<unknown> {\n const script = params.script as string;\n try {\n // biome-ignore lint/complexity/noCommaOperator lint/security/noGlobalEval: indirect eval is required for content script execution in extension context\n return await Promise.resolve((0, eval)(script));\n } catch (error) {\n throw new Error(error instanceof Error ? error.message : 'Script execution failed', {\n cause: error,\n });\n }\n}\n\nasync function handleGetElementInfo(params: Record<string, unknown>): Promise<unknown> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n return {\n matched: false,\n matchCount: 0,\n element: null,\n };\n }\n\n const rect = element.getBoundingClientRect();\n return {\n matched: true,\n matchCount: 1,\n element: {\n tagName: element.tagName.toLowerCase(),\n id: element.id,\n className: element.getAttribute('class') || '',\n role: getRole(element),\n accessibleName: getAccessibleName(element),\n label:\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ? (element.labels?.[0]?.textContent?.replace(/\\s+/g, ' ').trim() ?? null)\n : null,\n placeholder: element.getAttribute('placeholder'),\n testId: element.getAttribute('data-testid') || element.getAttribute('data-test-id'),\n textContent: element.textContent?.replace(/\\s+/g, ' ').trim().substring(0, 500) || '',\n value:\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ? element.value\n : null,\n visible: rect.width > 0 && rect.height > 0,\n enabled: !(\n element instanceof HTMLButtonElement ||\n element instanceof HTMLInputElement ||\n element instanceof HTMLSelectElement ||\n element instanceof HTMLTextAreaElement\n )\n ? true\n : !element.disabled,\n rect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n },\n };\n}\n\nasync function handleGetLocatorCandidates(params: Record<string, unknown>): Promise<unknown> {\n const locator = params as ElementLocator;\n const limit = typeof params.limit === 'number' ? Math.max(1, Math.min(10, params.limit)) : 5;\n const normalizeText = (value: string | null | undefined): string => (value ?? '').replace(/\\s+/g, ' ').trim();\n const matchesText = (actual: string | null | undefined, expected: string | undefined, exact = false): boolean => {\n if (!expected) {\n return false;\n }\n const normalizedActual = normalizeText(actual);\n const normalizedExpected = normalizeText(expected);\n if (!normalizedActual || !normalizedExpected) {\n return false;\n }\n return exact\n ? normalizedActual === normalizedExpected\n : normalizedActual.toLowerCase().includes(normalizedExpected.toLowerCase());\n };\n const getLabelText = (element: Element): string | null => {\n if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement\n ) {\n return element.labels?.[0]?.textContent ? normalizeText(element.labels[0].textContent) : null;\n }\n const wrappedLabel = element.closest('label');\n return wrappedLabel?.textContent ? normalizeText(wrappedLabel.textContent) : null;\n };\n\n const SKIP_TAGS = new Set(['html', 'body', 'head', 'script', 'style', 'noscript', 'template', 'meta', 'link']);\n const candidates = Array.from(document.querySelectorAll('*'))\n .map((element) => {\n if (SKIP_TAGS.has(element.tagName.toLowerCase())) return null;\n const accessibleName = getAccessibleName(element);\n const label = getLabelText(element);\n const placeholder = element.getAttribute('placeholder');\n const textContent = normalizeText(element.textContent);\n const role = getRole(element);\n const testId = element.getAttribute('data-testid') || element.getAttribute('data-test-id');\n const rect = element.getBoundingClientRect();\n const visible = rect.width > 0 && rect.height > 0;\n const enabled =\n !(\n element instanceof HTMLButtonElement ||\n element instanceof HTMLInputElement ||\n element instanceof HTMLSelectElement ||\n element instanceof HTMLTextAreaElement\n ) || !element.disabled;\n const reasons: string[] = [];\n let score = 0;\n let semanticSignals = 0;\n const exact = locator.exact ?? false;\n const isInteractive =\n role !== 'none' ||\n element instanceof HTMLButtonElement ||\n element instanceof HTMLInputElement ||\n element instanceof HTMLSelectElement ||\n element instanceof HTMLTextAreaElement ||\n (element instanceof HTMLAnchorElement && element.hasAttribute('href'));\n\n if (locator.role && role === locator.role) {\n score += 30;\n semanticSignals += 1;\n reasons.push('role match');\n }\n if (locator.name) {\n if (matchesText(accessibleName, locator.name, true)) {\n score += 60;\n semanticSignals += 1;\n reasons.push('exact accessible name match');\n } else if (matchesText(accessibleName, locator.name, exact)) {\n score += 35;\n semanticSignals += 1;\n reasons.push('accessible name match');\n }\n }\n if (locator.label) {\n if (matchesText(label, locator.label, true)) {\n score += 55;\n semanticSignals += 1;\n reasons.push('exact label match');\n } else if (matchesText(label, locator.label, exact)) {\n score += 30;\n semanticSignals += 1;\n reasons.push('label match');\n }\n }\n if (locator.placeholder && matchesText(placeholder, locator.placeholder, exact)) {\n score += 25;\n semanticSignals += 1;\n reasons.push('placeholder match');\n }\n if (locator.text && matchesText(textContent, locator.text, exact)) {\n score += 20;\n semanticSignals += 1;\n reasons.push('text match');\n }\n if (locator.testId && testId === locator.testId) {\n score += 50;\n semanticSignals += 1;\n reasons.push('test id match');\n }\n if (isInteractive) {\n score += 8;\n reasons.push('interactive element');\n }\n if (visible) {\n score += 10;\n reasons.push('visible');\n }\n if (enabled) {\n score += 5;\n reasons.push('enabled');\n }\n if (semanticSignals === 0) {\n return null;\n }\n\n return {\n score,\n reasons,\n candidate: {\n tagName: element.tagName.toLowerCase(),\n id: element.id,\n className: element.getAttribute('class') || '',\n role,\n accessibleName,\n label,\n placeholder,\n testId,\n textContent: textContent.slice(0, 500),\n visible,\n enabled,\n rect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n },\n };\n })\n .filter((entry): entry is NonNullable<typeof entry> => entry !== null && entry.score > 0)\n .sort((left, right) => right.score - left.score)\n .slice(0, limit);\n\n return {\n totalCandidates: candidates.length,\n candidates,\n };\n}\n\nasync function handleHover(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n element.scrollIntoView({ behavior: 'smooth', block: 'center' });\n\n const rect = element.getBoundingClientRect();\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n\n element.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, clientX: x, clientY: y }));\n element.dispatchEvent(new MouseEvent('mousemove', { bubbles: true, clientX: x, clientY: y }));\n}\n\nasync function handleSelect(params: Record<string, unknown>): Promise<void> {\n const locator = params as ElementLocator;\n const value = params.value as string | string[];\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n if (!(element instanceof HTMLSelectElement)) {\n throw new Error('Element is not a select element');\n }\n\n const values = Array.isArray(value) ? value : [value];\n\n for (const option of element.options) {\n option.selected = values.includes(option.value) || values.includes(option.text);\n }\n\n element.dispatchEvent(new Event('input', { bubbles: true }));\n element.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nasync function handleDrag(params: Record<string, unknown>): Promise<void> {\n const sourceLocator = params.source as ElementLocator;\n const targetLocator = params.target as ElementLocator;\n\n const sourceElement = await locateElement(sourceLocator);\n const targetElement = await locateElement(targetLocator);\n\n if (!sourceElement) {\n throw new Error('Source element not found');\n }\n\n if (!targetElement) {\n throw new Error('Target element not found');\n }\n\n const sourceRect = sourceElement.getBoundingClientRect();\n const targetRect = targetElement.getBoundingClientRect();\n\n const sourceX = sourceRect.left + sourceRect.width / 2;\n const sourceY = sourceRect.top + sourceRect.height / 2;\n const targetX = targetRect.left + targetRect.width / 2;\n const targetY = targetRect.top + targetRect.height / 2;\n const dataTransfer = new DataTransfer();\n\n sourceElement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: sourceX, clientY: sourceY }));\n sourceElement.dispatchEvent(\n new DragEvent('dragstart', {\n bubbles: true,\n clientX: sourceX,\n clientY: sourceY,\n dataTransfer,\n }),\n );\n\n targetElement.dispatchEvent(\n new DragEvent('dragenter', {\n bubbles: true,\n clientX: targetX,\n clientY: targetY,\n dataTransfer,\n }),\n );\n targetElement.dispatchEvent(\n new DragEvent('dragover', {\n bubbles: true,\n clientX: targetX,\n clientY: targetY,\n dataTransfer,\n }),\n );\n targetElement.dispatchEvent(\n new DragEvent('drop', {\n bubbles: true,\n clientX: targetX,\n clientY: targetY,\n dataTransfer,\n }),\n );\n\n sourceElement.dispatchEvent(\n new DragEvent('dragend', {\n bubbles: true,\n clientX: targetX,\n clientY: targetY,\n dataTransfer,\n }),\n );\n targetElement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: targetX, clientY: targetY }));\n}\n\nasync function handlePressKey(params: Record<string, unknown>): Promise<void> {\n const key = params.key as string;\n const modifiers = params.modifiers as string[] | undefined;\n\n const eventInit: KeyboardEventInit = {\n key,\n bubbles: true,\n ctrlKey: modifiers?.includes('Control') || modifiers?.includes('Ctrl'),\n shiftKey: modifiers?.includes('Shift'),\n altKey: modifiers?.includes('Alt'),\n metaKey: modifiers?.includes('Meta') || modifiers?.includes('Command'),\n };\n\n const activeElement = document.activeElement || document.body;\n activeElement.dispatchEvent(new KeyboardEvent('keydown', eventInit));\n activeElement.dispatchEvent(new KeyboardEvent('keypress', eventInit));\n activeElement.dispatchEvent(new KeyboardEvent('keyup', eventInit));\n}\n\nasync function handleWaitFor(params: Record<string, unknown>): Promise<void> {\n const selector = params.selector as string | undefined;\n const text = params.text as string | undefined;\n const state = (params.state as string) || 'visible';\n const timeout = (params.timeout as number) || DEFAULT_TOOL_TIMEOUT_MS;\n\n const startTime = Date.now();\n\n while (Date.now() - startTime < timeout) {\n if (selector) {\n const element = await locateElement({ selector });\n if (state === 'visible' && element && isVisible(element)) {\n return;\n }\n if (state === 'hidden' && (!element || !isVisible(element))) {\n return;\n }\n if (state === 'attached' && element) {\n return;\n }\n if (state === 'detached' && !element) {\n return;\n }\n }\n\n if (text) {\n const found = document.body.textContent?.includes(text);\n if (found) {\n return;\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n throw new Error(`Wait condition not met within ${timeout}ms`);\n}\n\nasync function handlePrepareForInput(params: Record<string, unknown>): Promise<unknown> {\n const locator = params as ElementLocator;\n const element = await locateElement(locator);\n\n if (!element) {\n throw new Error('Element not found');\n }\n\n element.scrollIntoView({ behavior: 'instant', block: 'center' });\n\n await new Promise((resolve) => setTimeout(resolve, 50));\n\n const rect = element.getBoundingClientRect();\n\n return {\n rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },\n tagName: element.tagName.toLowerCase(),\n isFocusable:\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement ||\n element.hasAttribute('contenteditable') ||\n element.getAttribute('tabindex') !== null,\n };\n}\n\nfunction isVisible(element: Element): boolean {\n const style = window.getComputedStyle(element);\n return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0';\n}\n"],"mappings":";AAuBA,IAAM,+BAAe,IAAI,KAA+B;AACxD,IAAI,aAAa;AASjB,SAAgB,UAAU,SAA0B;CAClD,MAAM,MAAM,IAAI,EAAE;AAClB,cAAa,IAAI,KAAK,IAAI,QAAQ,QAAQ,CAAC;AAC3C,QAAO;;AAGT,SAAgB,gBAAgB,KAA6B;AAE3D,QADY,aAAa,IAAI,IACtB,EAAK,OAAO,IAAI;;AAGzB,SAAgB,cAAoB;AAClC,cAAa,OAAO;AACpB,cAAa;;AAGf,SAAS,cAAc,OAA0C;AAC/D,SAAQ,SAAS,IAAI,QAAQ,QAAQ,IAAI,CAAC,MAAM;;AAGlD,SAAS,YAAY,QAAmC,UAAkB,QAAQ,OAAgB;CAChG,MAAM,mBAAmB,cAAc,OAAO;CAC9C,MAAM,qBAAqB,cAAc,SAAS;AAElD,KAAI,CAAC,oBAAoB,CAAC,mBACxB,QAAO;AAGT,KAAI,MACF,QAAO,qBAAqB;AAG9B,QAAO,iBAAiB,aAAa,CAAC,SAAS,mBAAmB,aAAa,CAAC;;AAGlF,SAAS,oBAAoB,SAAmD;CAC9E,MAAM,OAAO,QAAQ,MAAM;CAC3B,MAAM,QAAQ,KAAK;AACnB,MAAK,UAAU,QAAO,UAAU,QAAQ,KAAK,SAAS,MAAM,CAC1D,QAAO;EAAE,MAAM,KAAK,MAAM,GAAG,GAAG;EAAE,OAAO;EAAM;AAEjD,QAAO;EAAE;EAAM,OAAO;EAAO;;AAG/B,SAAS,sBAAsB,UAA2C;CACxE,MAAM,UAAU,SAAS,MAAM;AAE/B,KAAI,QAAQ,WAAW,QAAQ,EAAE;EAC/B,MAAM,SAAS,oBAAoB,QAAQ,MAAM,EAAe,CAAC;AACjE,SAAO;GAAE,MAAM;GAAQ,MAAM,OAAO;GAAM,OAAO,OAAO;GAAO;;CAGjE,MAAM,eAAe,QAAQ,MAAM,uCAAuC;AAC1E,KAAI,cAAc;EAChB,MAAM,SAAS,oBAAoB,aAAa,MAAM,GAAG;AACzD,SAAO;GACL,MAAM;GACN,SAAS,aAAa,IAAI,aAAa;GACvC,MAAM,OAAO;GACb,OAAO;GACR;;AAGH,QAAO;;AAGT,SAAS,+BAA+B,UAAkB,OAAuB;CAC/E,MAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACrE,wBAAO,IAAI,MACT,6BAA6B,SAAS,KAAK,OAAO,yIACnD;;AAGH,SAAS,qBAAqB,OAAyC;AACrE,KAAI,MAAM,QACR,QAAO,MAAM;CAGf,MAAM,UAAU,MAAM,aAAa,MAAM;AACzC,KAAI,SAAS;EACX,MAAM,SAAS,SAAS,eAAe,QAAQ;AAC/C,MAAI,OACF,QAAO;;AAIX,QAAO,MAAM,cAAc,+BAA+B;;AAO5D,SAAgB,oBAAkB,SAA0B;CAC1D,MAAM,YAAY,QAAQ,aAAa,aAAa;AACpD,KAAI,UACF,QAAO,cAAc,UAAU;CAGjC,MAAM,aAAa,QAAQ,aAAa,kBAAkB;AAC1D,KAAI,YAAY;EACd,MAAM,SAAS,WACZ,MAAM,MAAM,CACZ,KAAK,OAAO,cAAc,SAAS,eAAe,GAAG,EAAE,YAAY,CAAC,CACpE,OAAO,QAAQ;AAClB,MAAI,OAAO,SAAS,EAClB,QAAO,OAAO,KAAK,IAAI;;AAI3B,KACE,mBAAmB,oBACnB,mBAAmB,uBACnB,mBAAmB,mBACnB;AACA,MAAI,QAAQ,IAAI;GACd,MAAM,QAAQ,SAAS,cAAc,cAAc,IAAI,OAAO,QAAQ,GAAG,CAAC,IAAI;AAC9E,OAAI,OAAO,YACT,QAAO,cAAc,MAAM,YAAY;;AAG3C,MAAI,QAAQ,YACV,QAAO,cAAc,QAAQ,YAAY;;CAI7C,MAAM,QAAQ,QAAQ,QAAQ,QAAQ;AACtC,KAAI,OAAO,YACT,QAAO,cAAc,MAAM,YAAY;AAGzC,KAAI,mBAAmB,oBAAoB,QAAQ,IACjD,QAAO,cAAc,QAAQ,IAAI;AAGnC,KAAI,QAAQ,YACV,QAAO,cAAc,QAAQ,YAAY;AAG3C,QAAO;;AAGT,SAAgB,UAAQ,SAA0B;CAChD,MAAM,WAAW,QAAQ,aAAa,OAAO;AAC7C,KAAI,SACF,QAAO;AAGT,KAAI,mBAAmB,iBAgBrB,QAAO;EAbL,QAAQ;EACR,UAAU;EACV,OAAO;EACP,QAAQ;EACR,UAAU;EACV,OAAO;EACP,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,KAAK;EACL,MAAM;EACN,KAAK;EAEA,EAfO,QAAQ,QAAQ,QAAQ,aAepB,KAAS;CAG7B,MAAM,UAAU,QAAQ,QAAQ,aAAa;AAgC7C,QAAO;EA9BL,GAAG,QAAQ,aAAa,OAAO,GAAG,SAAS;EAC3C,SAAS;EACT,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,MAAM;EACN,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,QAAQ;EACR,KAAK;EACL,IAAI;EACJ,MAAM;EACN,KAAK;EACL,IAAI;EACJ,QAAQ;EACR,UAAU;EACV,SAAS,QAAQ,aAAa,aAAa,GAAG,WAAW;EACzD,QAAQ;EACR,OAAO;EACP,IAAI;EACJ,UAAU;EACV,IAAI;EACJ,IAAI;EACJ,IAAI;EAGC,CAAQ,YAAY;;AAG7B,SAAS,cAAyB;AAChC,QAAO,MAAM,KAAK,SAAS,iBAAiB,IAAI,CAAC;;AAGnD,SAAS,WAAW,SAAyC;AAC3D,KAAI,CAAC,QAAQ,KACX,QAAO;CAGT,MAAM,aAAa,aAAa,CAAC,QAAQ,YAAY,UAAQ,QAAQ,KAAK,QAAQ,KAAK;AACvF,KAAI,CAAC,QAAQ,KACX,QAAO,WAAW,MAAM;AAG1B,QAAO,WAAW,MAAM,YAAY,YAAY,oBAAkB,QAAQ,EAAE,QAAQ,MAAO,QAAQ,MAAM,CAAC,IAAI;;AAGhH,SAAS,YAAY,SAAyC;AAC5D,KAAI,CAAC,QAAQ,MACX,QAAO;CAGT,MAAM,SAAS,MAAM,KAAK,SAAS,iBAAiB,QAAQ,CAAC,CAAC,QAAQ,UACpE,YAAY,MAAM,aAAa,QAAQ,OAAQ,QAAQ,MAAM,CAC9D;AAED,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,UAAU,qBAAqB,MAA0B;AAC/D,MAAI,QACF,QAAO;;AAIX,QAAO,OAAO,MAAM;;AAGtB,SAAS,kBAAkB,SAAyC;AAClE,KAAI,CAAC,QAAQ,YACX,QAAO;AAGT,QACE,aAAa,CAAC,MAAM,YAAY;AAE9B,SAAO,YADa,QAAQ,aAAa,cACtB,EAAa,QAAQ,aAAc,QAAQ,MAAM;GACpE,IAAI;;AAIV,SAAS,WAAW,SAAyC;AAC3D,KAAI,CAAC,QAAQ,KACX,QAAO;CAGT,MAAM,aAAa,aAAa,CAAC,QAAQ,YAAY,YAAY,QAAQ,aAAa,QAAQ,MAAO,QAAQ,MAAM,CAAC;AACpH,KAAI,WAAW,WAAW,EACxB,QAAO;AAGT,MAAK,MAAM,aAAa,WACtB,KAAI,qBAAqB,kBAAkB;EACzC,MAAM,UAAU,qBAAqB,UAAU;AAC/C,MAAI,QACF,QAAO;;AAKb,QAAO,WAAW;;AAGpB,SAAS,aAAa,SAAyC;AAC7D,KAAI,CAAC,QAAQ,OACX,QAAO;AAGT,QAAO,SAAS,cAAc,iBAAiB,IAAI,OAAO,QAAQ,OAAO,CAAC,IAAI;;AAGhF,SAAS,uBAAuB,UAA4C;AAC1E,KAAI,SAAS,SAAS,OACpB,QAAO,WAAW;EAAE,MAAM,SAAS;EAAM,OAAO,SAAS;EAAO,CAAC;AAMnE,SAHiB,SAAS,UACtB,aAAa,CAAC,QAAQ,YAAY,QAAQ,QAAQ,aAAa,KAAK,SAAS,QAAQ,GACrF,aAAa,EACD,MAAM,YAAY,YAAY,QAAQ,aAAa,SAAS,KAAK,CAAC,IAAI;;AAGxF,eAAsB,cAAc,SAAkD;AAEpF,KAAI,QAAQ,KAAK;EACf,MAAM,UAAU,gBAAgB,QAAQ,IAAI;AAC5C,MAAI,QAAS,QAAO;;CAItB,MAAM,kBAAkB;EACtB,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB,kBAAkB,QAAQ;EAC1B,WAAW,QAAQ;EACnB,aAAa,QAAQ;EACtB;AACD,MAAK,MAAM,WAAW,gBACpB,KAAI,QACF,QAAO;AAKX,KAAI,QAAQ,UAAU;AACpB,MAAI,QAAQ,KAAK,QAAQ,SAAS,MAAM,CAAC,CACvC,OAAM,IAAI,MACR,6DAA6D,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,CAAC,mGAC/F;EAEH,MAAM,WAAW,sBAAsB,QAAQ,SAAS;AACxD,MAAI,UAAU;GACZ,MAAM,UAAU,uBAAuB,SAAS;AAChD,OAAI,QAAS,QAAO;QAEpB,KAAI;GACF,MAAM,UAAU,SAAS,cAAc,QAAQ,SAAS;AACxD,OAAI,QAAS,QAAO;WACb,OAAO;AACd,SAAM,+BAA+B,QAAQ,UAAU,MAAM;;;AAMnE,KAAI,QAAQ,OAAO;EACjB,MAAM,SAAS,SAAS,SAAS,QAAQ,OAAO,UAAU,MAAM,YAAY,yBAAyB,KAAK;AAC1G,MAAI,OAAO,2BAA2B,QACpC,QAAO,OAAO;;AAKlB,KAAI,QAAQ,MAAM;EAChB,MAAM,UAAU,aAAa,CAAC,MAAM,cAClC,YAAY,oBAAkB,UAAU,EAAE,QAAQ,MAAO,QAAQ,MAAM,CACxE;AACD,MAAI,QACF,QAAO;;AAIX,QAAO;;;;;;;;;;ACxWT,SAAgB,uBAAuB,cAA0C;AAE/E,cAAa;AAIb,QADa,UADO,eAAgB,SAAS,cAAc,aAAa,IAAI,SAAS,OAAQ,SAAS,MACvD,EACxC,IAAQ;EAAE,KAAK;EAAQ,MAAM;EAAQ,MAAM;EAAc;;AAGlE,SAAS,UAAU,SAAkB,OAAyC;CAE5E,MAAM,QAAQ,iBAAiB,QAAQ;AACvC,KAAI,MAAM,YAAY,UAAU,MAAM,eAAe,SACnD,QAAO;CAGT,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,OAAO,kBAAkB,QAAQ;CACvC,MAAM,MAAM,UAAU,QAAQ;CAG9B,MAAM,WAAgC,EAAE;AACxC,MAAK,MAAM,SAAS,QAAQ,UAAU;EACpC,MAAM,YAAY,UAAU,OAAO,QAAQ,EAAE;AAC7C,MAAI,UACF,UAAS,KAAK,UAAU;;AAK5B,KAAI,SAAS,UAAU,CAAC,QAAQ,SAAS,WAAW,EAClD,QAAO,SAAS;CAGlB,MAAM,OAA0B;EAC9B;EACA;EACD;AAED,KAAI,KAAM,MAAK,OAAO;AACtB,KAAI,SAAS,SAAS,EAAG,MAAK,WAAW;AAGzC,oBAAmB,SAAS,KAAK;AAEjC,QAAO;;AAGT,SAAS,QAAQ,SAA0B;CAEzC,MAAM,WAAW,QAAQ,aAAa,OAAO;AAC7C,KAAI,SAAU,QAAO;CAGrB,MAAM,UAAU,QAAQ,QAAQ,aAAa;AAkC7C,QAAO;EAhCL,GAAG,QAAQ,aAAa,OAAO,GAAG,SAAS;EAC3C,SAAS;EACT,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,MAAM;EACN,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,QAAQ;EACR,KAAK;EACL,OAAO,aAAa,QAA4B;EAChD,IAAI;EACJ,MAAM;EACN,KAAK;EACL,IAAI;EACJ,QAAQ;EACR,UAAU;EACV,SAAS,QAAQ,aAAa,aAAa,GAAG,WAAW;EACzD,QAAQ;EACR,OAAO;EACP,OAAO;EACP,IAAI;EACJ,UAAU;EACV,IAAI;EACJ,IAAI;EACJ,IAAI;EAGC,CAAQ,YAAY;;AAG7B,SAAS,aAAa,OAAiC;AAgBrD,QAAO;EAbL,QAAQ;EACR,UAAU;EACV,OAAO;EACP,QAAQ;EACR,UAAU;EACV,OAAO;EACP,OAAO;EACP,QAAQ;EACR,QAAQ;EACR,KAAK;EACL,MAAM;EACN,KAAK;EAEA,EAfO,MAAM,QAAQ,QAAQ,aAelB,KAAS;;AAG7B,SAAS,kBAAkB,SAAsC;CAE/D,MAAM,YAAY,QAAQ,aAAa,aAAa;AACpD,KAAI,UAAW,QAAO;CAGtB,MAAM,aAAa,QAAQ,aAAa,kBAAkB;AAC1D,KAAI,YAAY;EACd,MAAM,SAAS,WACZ,MAAM,IAAI,CACV,KAAK,OAAO,SAAS,eAAe,GAAG,EAAE,YAAY,CACrD,OAAO,QAAQ,CACf,KAAK,IAAI;AACZ,MAAI,OAAQ,QAAO;;AAIrB,KAAI,mBAAmB,oBAAoB,mBAAmB,qBAAqB;EACjF,MAAM,KAAK,QAAQ;AACnB,MAAI,IAAI;GACN,MAAM,QAAQ,SAAS,cAAc,cAAc,GAAG,IAAI;AAC1D,OAAI,OAAO,YAAa,QAAO,MAAM,YAAY,MAAM;;;CAK3D,MAAM,UAAU,QAAQ,QAAQ,aAAa;AAC7C,KAAI;EAAC;EAAU;EAAK;EAAM;EAAM;EAAM;EAAM;EAAM;EAAM;EAAS;EAAS,CAAC,SAAS,QAAQ,EAAE;EAC5F,MAAM,OAAO,QAAQ,aAAa,MAAM;AACxC,MAAI,QAAQ,KAAK,SAAS,IAAK,QAAO;;AAIxC,KAAI,mBAAmB,oBAAoB,QAAQ,IACjD,QAAO,QAAQ;AAIjB,KAAI,mBAAmB,oBAAoB,QAAQ,YACjD,QAAO,QAAQ;;AAMnB,SAAS,mBAAmB,SAAkB,MAA+B;AAE3E,KAAI,SAAS,kBAAkB,QAC7B,MAAK,UAAU;AAIjB,KAAK,QAA6B,SAChC,MAAK,WAAW;AAIlB,KAAI,mBAAmB;MACjB,QAAQ,SAAS,cAAc,QAAQ,SAAS,QAClD,MAAK,UAAU,QAAQ,gBAAgB,UAAU,QAAQ;;AAK7D,KAAI,mBAAmB,kBACrB,MAAK,WAAW,QAAQ;CAI1B,MAAM,eAAe,QAAQ,aAAa,gBAAgB;AAC1D,KAAI,aACF,MAAK,WAAW,iBAAiB;CAInC,MAAM,eAAe,QAAQ,QAAQ,MAAM,aAAa;AACxD,KAAI,aACF,MAAK,QAAQ,OAAO,SAAS,aAAa,IAAI,GAAG;CAInD,MAAM,cAAc,QAAQ,aAAa,eAAe;AACxD,KAAI,YACF,MAAK,UAAU,gBAAgB,UAAU,UAAU,gBAAgB;;;;;;;;ACrNvE,SAAgB,0BAAgC;CAC9C,MAAM,SAAS;AACf,KAAK,WAAuC,QAC1C;AAED,YAAuC,UAAU;CAElD,MAAM,kBAAkB;EACtB,MAAM,IAAI;AACV,MAAI,EAAE,+BACJ;AAEF,IAAE,iCAAiC;AAGnC,SAAO,eAAe,WAAW,aAAa;GAC5C,WAAW,KAAA;GACX,cAAc;GACf,CAAC;AAGF,MAAI,UAAU,sBAAsB,EAClC,QAAO,eAAe,WAAW,uBAAuB;GACtD,WAAW;GACX,cAAc;GACf,CAAC;EAKJ,MAAM,gBAAgB,UAAU,YAAY,MAAM,KAAK,UAAU,YAAY;AAC7E,YAAU,YAAY,SAAS,eAAqC;AAClE,OAAI,WAAW,SAAS,gBACtB,QAAO,QAAQ,QAAQ;IAAE,OAAO;IAAU,UAAU;IAAM,CAAqB;AAEjF,UAAO,cAAc,WAAW;;AAKlC,MADqB,UAA8C,QAAQ,WACvD,EAClB,QAAO,eAAe,WAAW,WAAW;GAC1C,WAAW;IACT,MAAM,UAAU;KACd;MAAE,MAAM;MAAc,UAAU;MAAuB,aAAa;MAA4B;KAChG;MACE,MAAM;MACN,UAAU;MACV,aAAa;MACd;KACD;MACE,MAAM;MACN,UAAU;MACV,aAAa;MACd;KACD;MACE,MAAM;MACN,UAAU;MACV,aAAa;MACd;KACF;IACD,MAAM,MAA+B,EAAE,QAAQ,QAAQ,QAAQ;AAC/D,SAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,IAClC,KAAI,KAAK,QAAQ;AAEnB,WAAO;;GAET,cAAc;GACf,CAAC;AAKJ,MAAI;GACF,MAAM,IAAI;GACV,MAAM,KAAK,EAAE;AACb,OAAI,MAAM,GAAG,WAAY,GAAG,QAAoC,IAAI;IAClE,MAAM,cAAc,GAAG;IACvB,MAAM,UAAiD,EACrD,IAAI,QAAQ,MAAM;AAChB,SAAI,SAAS,KACX;KAEF,MAAM,QAAQ,QAAQ,IAAI,QAAQ,KAAK;AACvC,YAAO,OAAO,UAAU,aAAa,MAAM,KAAK,OAAO,GAAG;OAE7D;AACD,MAAE,SAAS,IAAI,MAAM,IAAI,EACvB,IAAI,QAAQ,MAAM;AAChB,SAAI,SAAS,UACX,QAAO,IAAI,MAAM,aAAa,QAAQ;AAExC,YAAO,QAAQ,IAAI,QAAQ,KAAK;OAEnC,CAAC;;UAEE;AAKR,SAAO;GACL,MAAM,OAAQ,KAAK,QAAQ,GAAG,eAAgB;GAE9C,MAAM,cAAc,UAA0B;AAC5C,aAAS,SAAS;AAClB,aAAS,UAAU;AACnB,aAAS,SAAS;AAClB,WAAO,UAAU;;GAGnB,MAAM,iBAAiB,UAA0B;AAE/C,WADa,WAAW,OAAS,QAAQ,eAAgB,EACjD,GAAO,IAAK;;GAGtB,MAAM,mBAAmB,yBAAyB,UAAU;AAC5D,4BAAyB,UAAU,eAAe,SAChD,GAAG,MACH;IACA,MAAM,YAAY,iBAAiB,MAAM,MAAM,KAA4C;IAC3F,MAAM,EAAE,SAAS;AACjB,SAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,IAAI;KACxC,MAAM,IAAI,cAAc,MAAM,EAAE;AAChC,UAAK,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;AACjD,UAAK,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,EAAE,CAAC;;AAE3D,WAAO;;GAGT,MAAM,gBAAgB,kBAAkB,UAAU;AAClD,qBAAkB,UAAU,YAAY,SAAU,GAAG,MAA0B;AAC7E,QAAI;KACF,MAAM,MAAM,KAAK,WAAW,KAAK;AACjC,SAAI,KAAK;MACP,MAAM,MAAM,IAAI,aAAa,GAAG,GAAG,KAAK,OAAO,KAAK,OAAO;AAC3D,UAAI,aAAa,KAAK,GAAG,EAAE;;YAEvB;AAGR,WAAO,cAAc,MAAM,MAAM,KAAyC;;GAG5E,MAAM,aAAa,kBAAkB,UAAU;AAC/C,qBAAkB,UAAU,SAAS,SAAU,UAAwB,GAAG,MAA0B;AAClG,QAAI;KACF,MAAM,MAAM,KAAK,WAAW,KAAK;AACjC,SAAI,KAAK;MACP,MAAM,MAAM,IAAI,aAAa,GAAG,GAAG,KAAK,OAAO,KAAK,OAAO;AAC3D,UAAI,aAAa,KAAK,GAAG,EAAE;;YAEvB;AAGR,WAAO,WAAW,KAChB,MACA,UACA,GAAI,KACL;;MAED;AAGJ,SAAO;GACL,MAAM,iBAAiB;GACvB,MAAM,mBAAmB;GACzB,MAAM,kBAAkB;GACxB,MAAM,oBAAoB;GAE1B,MAAM,qBAAqB,UAAwD;IACjF,MAAM,WAAW,MAAM;AACvB,UAAM,eAAe,SAAU,OAAe;AAC5C,SAAI,UAAU,gBAAiB,QAAO;AACtC,SAAI,UAAU,kBAAmB,QAAO;AACxC,YAAO,SAAS,KAAK,MAAM,MAAM;;;AAIrC,OAAI,OAAO,0BAA0B,YACnC,mBAAkB,sBAAsB,UAAU;AAEpD,OAAI,OAAO,2BAA2B,YACpC,mBAAkB,uBAAuB,UAAU;MAEnD;;CAGN,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,cAAc,IAAI,UAAU,UAAU,CAAC;AAC9C,EAAC,SAAS,mBAAmB,SAAS,QAAQ,SAAS,MAAM,YAAY,OAAO;AAChF,QAAO,QAAQ;;;;;;;;;;;;;ACtLjB,yBAAyB;;;;AAKzB,IAAM,gBAAgB;CACpB,OAAO;CACP,MAAM;CACN,MAAM;CACN,cAAc;CACd,iBAAiB;CACjB,kBAAkB;CAClB,wBAAwB;CACxB,OAAO;CACP,QAAQ;CACR,MAAM;CACN,WAAW;CACX,UAAU;CACV,mBAAmB;CACpB;AAED,IAAM,0BAA0B;AAoBhC,IAAM,gBAAgB,IAAI,IAAI,OAAO,OAAO,cAAc,CAAC;AAE3D,SAAS,wBAA8B;CACrC,MAAM,SAAS;AACf,KAAK,WAAuC,QAC1C;AAED,YAAuC,UAAU;CAElD,MAAM,kBAAkB;EACtB,MAAM,UAAU;AAchB,MAAI,QAAQ,sCACV;AAEF,UAAQ,wCAAwC;AAEhD,MAAI,CAAC,QAAQ,2BACX,SAAQ,6BAA6B;GAAE,gBAAgB;GAAG,UAAU,EAAE;GAAE;EAE1E,MAAM,QAAQ,QAAQ;EAEtB,MAAM,eAAe;EACrB,MAAM,iBAAiB;GAAC;GAAO;GAAQ;GAAQ;GAAS;GAAS;GAAQ;EAEzE,MAAM,gBAAgB,UAA2B;AAC/C,OAAI,OAAO,UAAU,SACnB,QAAO;AAET,OAAI,iBAAiB,MACnB,QAAO,MAAM,SAAS,MAAM;AAE9B,OAAI;AACF,WAAO,KAAK,UAAU,MAAM;WACtB;AACN,WAAO,OAAO,MAAM;;;AAIxB,OAAK,MAAM,UAAU,gBAAgB;GACnC,MAAM,WAAW,QAAQ,QAAQ,KAAK,QAAQ;AAC9C,WAAQ,WAAW,GAAG,SAAoB;IACxC,MAAM,OAAO,KAAK,KAAK,QAAQ,aAAa,IAAI,CAAC,CAAC,KAAK,IAAI;AAC3D,UAAM,SAAS,KAAK;KAClB,IAAI,OAAO,EAAE,MAAM;KACnB,MAAM,WAAW,SAAS,YAAY;KACtC;KACA,UAAU;MACR,KAAK,OAAO,SAAS;MACrB,YAAY;MACZ,cAAc;MACf;KACD,4BAAW,IAAI,MAAM,EAAC,aAAa;KACpC,CAAC;AACF,QAAI,MAAM,SAAS,SAAS,aAC1B,OAAM,SAAS,OAAO,GAAG,MAAM,SAAS,SAAS,aAAa;AAEhE,WAAO,SAAS,GAAG,KAAK;;;;CAK9B,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,QAAO,cAAc,IAAI,UAAU,UAAU,CAAC;AAC9C,EAAC,SAAS,mBAAmB,SAAS,QAAQ,SAAS,MAAM,YAAY,OAAO;AAChF,QAAO,QAAQ;;AAGjB,SAAS,wBAAwB,QAA+D;CAC9F,MAAM,YAAY,OAAO;AACzB,KAAI,CAAC,aAAa,OAAO,cAAc,SACrC;CAGF,MAAM,UACJ,OAAQ,UAAoC,YAAY,WACnD,UAAkC,UACnC,KAAA;CACN,MAAM,SACJ,OAAQ,UAAmC,WAAW,WACjD,UAAiC,SAClC,KAAA;AAEN,KAAI,CAAC,WAAW,CAAC,OACf;AAGF,QAAO;EAAE;EAAS;EAAQ;;AAG5B,eAAe,cACb,OACA,SACA,QACA,kBACe;AACf,KAAI;AACF,QAAM,OAAO,QAAQ,YAAY;GAC/B,MAAM;GACN;GACA;GACA,SAAS;GACT,YAAY;IACV,8BAA8B;IAC9B,wBAAwB,SAAS;IAClC;GACF,CAAC;SACI;;AAKV,SAAS,gBAAgB,SAAyC;AAChE,KAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;CACpD,MAAM,MAAM;AACZ,KAAI,OAAO,IAAI,WAAW,YAAY,CAAC,cAAc,IAAI,IAAI,OAA4B,CAAE,QAAO;AAClG,KAAI,IAAI,WAAW,KAAA,MAAc,OAAO,IAAI,WAAW,YAAY,IAAI,WAAW,MAAO,QAAO;AAChG,QAAO;EACL,QAAQ,IAAI;EACZ,QAAS,IAAI,UAAsC,EAAE;EACtD;;AAGH,OAAO,QAAQ,UAAU,aACtB,SAAkB,SAAuC,iBAAsD;CAC9G,MAAM,YAAY,gBAAgB,QAAQ;AAC1C,KAAI,CAAC,WAAW;AACd,eAAa;GACX,SAAS;GACT,OAAO;GACR,CAAC;AACF,SAAO;;CAGT,MAAM,mBAAmB,wBAAwB,UAAU,OAAO;AAC7D,eAAc,SAAS,2BAA2B,UAAU,QAAQ,iBAAiB;AAE1F,qBAAoB,UAAU,CAC3B,MAAM,WAAW;AACX,gBAAc,SAAS,4BAA4B,UAAU,QAAQ,iBAAiB;AAC3F,eAAa;GAAE,SAAS;GAAM;GAAQ,CAAC;GACvC,CACD,OAAO,UAAiB;AAClB,gBAAc,SAAS,MAAM,SAAS,UAAU,QAAQ,iBAAiB;AAC9E,eAAa;GAAE,SAAS;GAAO,OAAO,MAAM;GAAS,CAAC;GACtD;AACJ,QAAO;EAEV;AAED,uBAAuB;AAEvB,eAAe,oBAAoB,SAA2C;CAC5E,MAAM,EAAE,QAAQ,WAAW;AAE3B,SAAQ,QAAR;EACE,KAAK,cAAc,MACjB,QAAO,YAAY,OAAO;EAC5B,KAAK,cAAc,KACjB,QAAO,WAAW,OAAO;EAC3B,KAAK,cAAc,KACjB,QAAO,WAAW,OAAO;EAC3B,KAAK,cAAc,aACjB,QAAO,uBAAuB,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO,KAAA,EAAU;EAC1F,KAAK,cAAc,gBACjB,QAAO,qBAAqB,OAAO;EACrC,KAAK,cAAc,iBACjB,QAAO,qBAAqB,OAAO;EACrC,KAAK,cAAc,uBACjB,QAAO,2BAA2B,OAAO;EAC3C,KAAK,cAAc,MACjB,QAAO,YAAY,OAAO;EAC5B,KAAK,cAAc,OACjB,QAAO,aAAa,OAAO;EAC7B,KAAK,cAAc,KACjB,QAAO,WAAW,OAAO;EAC3B,KAAK,cAAc,UACjB,QAAO,eAAe,OAAO;EAC/B,KAAK,cAAc,SACjB,QAAO,cAAc,OAAO;EAC9B,KAAK,cAAc,kBACjB,QAAO,sBAAsB,OAAO;;;AAI1C,eAAe,YAAY,QAAgD;CAEzE,MAAM,UAAU,MAAM,cAAc,OAAQ;AAE5C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,oBAAoB;AAItC,SAAQ,eAAe;EAAE,UAAU;EAAU,OAAO;EAAU,CAAC;CAG/D,MAAM,OAAO,QAAQ,uBAAuB;CAC5C,MAAM,IAAI,KAAK,OAAO,KAAK,QAAQ;CACnC,MAAM,IAAI,KAAK,MAAM,KAAK,SAAS;AAEnC,SAAQ,cAAc,IAAI,WAAW,aAAa;EAAE,SAAS;EAAM,SAAS;EAAG,SAAS;EAAG,CAAC,CAAC;AAC7F,SAAQ,cAAc,IAAI,WAAW,WAAW;EAAE,SAAS;EAAM,SAAS;EAAG,SAAS;EAAG,CAAC,CAAC;AAC3F,SAAQ,cAAc,IAAI,WAAW,SAAS;EAAE,SAAS;EAAM,SAAS;EAAG,SAAS;EAAG,CAAC,CAAC;;AAG3F,eAAe,WAAW,QAAgD;CACxE,MAAM,UAAU;CAChB,MAAM,QAAQ,OAAO;CACrB,MAAM,UAAU,MAAM,cAAc,QAAQ;AAE5C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,KAAI,EAAE,mBAAmB,oBAAoB,mBAAmB,qBAC9D,OAAM,IAAI,MAAM,sCAAsC;AAIxD,SAAQ,OAAO;AACf,SAAQ,QAAQ;AAGhB,SAAQ,QAAQ;AAChB,SAAQ,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,MAAM,CAAC,CAAC;AAC5D,SAAQ,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,MAAM,CAAC,CAAC;;AAG/D,eAAe,WAAW,QAAgD;CACxE,MAAM,UAAU;CAChB,MAAM,OAAO,OAAO;CACpB,MAAM,UAAU,MAAM,cAAc,QAAQ;AAE5C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,KAAI,mBAAmB,YACrB,SAAQ,OAAO;AAIjB,MAAK,MAAM,QAAQ,MAAM;AACvB,UAAQ,cAAc,IAAI,cAAc,WAAW;GAAE,KAAK;GAAM,SAAS;GAAM,CAAC,CAAC;AACjF,UAAQ,cAAc,IAAI,cAAc,YAAY;GAAE,KAAK;GAAM,SAAS;GAAM,CAAC,CAAC;AAElF,MAAI,mBAAmB,oBAAoB,mBAAmB,qBAAqB;AACjF,WAAQ,SAAS;AACjB,WAAQ,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,MAAM,CAAC,CAAC;;AAG9D,UAAQ,cAAc,IAAI,cAAc,SAAS;GAAE,KAAK;GAAM,SAAS;GAAM,CAAC,CAAC;;;AAInF,eAAe,qBAAqB,QAAmD;CACrF,MAAM,SAAS,OAAO;AACtB,KAAI;AAEF,SAAO,MAAM,QAAQ,SAAS,GAAG,MAAM,OAAO,CAAC;UACxC,OAAO;AACd,QAAM,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,2BAA2B,EAClF,OAAO,OACR,CAAC;;;AAIN,eAAe,qBAAqB,QAAmD;CAErF,MAAM,UAAU,MAAM,cAAc,OAAQ;AAE5C,KAAI,CAAC,QACH,QAAO;EACL,SAAS;EACT,YAAY;EACZ,SAAS;EACV;CAGH,MAAM,OAAO,QAAQ,uBAAuB;AAC5C,QAAO;EACL,SAAS;EACT,YAAY;EACZ,SAAS;GACP,SAAS,QAAQ,QAAQ,aAAa;GACtC,IAAI,QAAQ;GACZ,WAAW,QAAQ,aAAa,QAAQ,IAAI;GAC5C,MAAM,UAAQ,QAAQ;GACtB,gBAAgB,oBAAkB,QAAQ;GAC1C,OACE,mBAAmB,oBACnB,mBAAmB,uBACnB,mBAAmB,oBACd,QAAQ,SAAS,IAAI,aAAa,QAAQ,QAAQ,IAAI,CAAC,MAAM,IAAI,OAClE;GACN,aAAa,QAAQ,aAAa,cAAc;GAChD,QAAQ,QAAQ,aAAa,cAAc,IAAI,QAAQ,aAAa,eAAe;GACnF,aAAa,QAAQ,aAAa,QAAQ,QAAQ,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,IAAI;GACnF,OACE,mBAAmB,oBACnB,mBAAmB,uBACnB,mBAAmB,oBACf,QAAQ,QACR;GACN,SAAS,KAAK,QAAQ,KAAK,KAAK,SAAS;GACzC,SAAS,EACP,mBAAmB,qBACnB,mBAAmB,oBACnB,mBAAmB,qBACnB,mBAAmB,uBAEjB,OACA,CAAC,QAAQ;GACb,MAAM;IACJ,GAAG,KAAK;IACR,GAAG,KAAK;IACR,OAAO,KAAK;IACZ,QAAQ,KAAK;IACd;GACF;EACF;;AAGH,eAAe,2BAA2B,QAAmD;CAC3F,MAAM,UAAU;CAChB,MAAM,QAAQ,OAAO,OAAO,UAAU,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC,GAAG;CAC3F,MAAM,iBAAiB,WAA8C,SAAS,IAAI,QAAQ,QAAQ,IAAI,CAAC,MAAM;CAC7G,MAAM,eAAe,QAAmC,UAA8B,QAAQ,UAAmB;AAC/G,MAAI,CAAC,SACH,QAAO;EAET,MAAM,mBAAmB,cAAc,OAAO;EAC9C,MAAM,qBAAqB,cAAc,SAAS;AAClD,MAAI,CAAC,oBAAoB,CAAC,mBACxB,QAAO;AAET,SAAO,QACH,qBAAqB,qBACrB,iBAAiB,aAAa,CAAC,SAAS,mBAAmB,aAAa,CAAC;;CAE/E,MAAM,gBAAgB,YAAoC;AACxD,MACE,mBAAmB,oBACnB,mBAAmB,uBACnB,mBAAmB,kBAEnB,QAAO,QAAQ,SAAS,IAAI,cAAc,cAAc,QAAQ,OAAO,GAAG,YAAY,GAAG;EAE3F,MAAM,eAAe,QAAQ,QAAQ,QAAQ;AAC7C,SAAO,cAAc,cAAc,cAAc,aAAa,YAAY,GAAG;;CAG/E,MAAM,YAAY,IAAI,IAAI;EAAC;EAAQ;EAAQ;EAAQ;EAAU;EAAS;EAAY;EAAY;EAAQ;EAAO,CAAC;CAC9G,MAAM,aAAa,MAAM,KAAK,SAAS,iBAAiB,IAAI,CAAC,CAC1D,KAAK,YAAY;AAChB,MAAI,UAAU,IAAI,QAAQ,QAAQ,aAAa,CAAC,CAAE,QAAO;EACzD,MAAM,iBAAiB,oBAAkB,QAAQ;EACjD,MAAM,QAAQ,aAAa,QAAQ;EACnC,MAAM,cAAc,QAAQ,aAAa,cAAc;EACvD,MAAM,cAAc,cAAc,QAAQ,YAAY;EACtD,MAAM,OAAO,UAAQ,QAAQ;EAC7B,MAAM,SAAS,QAAQ,aAAa,cAAc,IAAI,QAAQ,aAAa,eAAe;EAC1F,MAAM,OAAO,QAAQ,uBAAuB;EAC5C,MAAM,UAAU,KAAK,QAAQ,KAAK,KAAK,SAAS;EAChD,MAAM,UACJ,EACE,mBAAmB,qBACnB,mBAAmB,oBACnB,mBAAmB,qBACnB,mBAAmB,wBAChB,CAAC,QAAQ;EAChB,MAAM,UAAoB,EAAE;EAC5B,IAAI,QAAQ;EACZ,IAAI,kBAAkB;EACtB,MAAM,QAAQ,QAAQ,SAAS;EAC/B,MAAM,gBACJ,SAAS,UACT,mBAAmB,qBACnB,mBAAmB,oBACnB,mBAAmB,qBACnB,mBAAmB,uBAClB,mBAAmB,qBAAqB,QAAQ,aAAa,OAAO;AAEvE,MAAI,QAAQ,QAAQ,SAAS,QAAQ,MAAM;AACzC,YAAS;AACT,sBAAmB;AACnB,WAAQ,KAAK,aAAa;;AAE5B,MAAI,QAAQ;OACN,YAAY,gBAAgB,QAAQ,MAAM,KAAK,EAAE;AACnD,aAAS;AACT,uBAAmB;AACnB,YAAQ,KAAK,8BAA8B;cAClC,YAAY,gBAAgB,QAAQ,MAAM,MAAM,EAAE;AAC3D,aAAS;AACT,uBAAmB;AACnB,YAAQ,KAAK,wBAAwB;;;AAGzC,MAAI,QAAQ;OACN,YAAY,OAAO,QAAQ,OAAO,KAAK,EAAE;AAC3C,aAAS;AACT,uBAAmB;AACnB,YAAQ,KAAK,oBAAoB;cACxB,YAAY,OAAO,QAAQ,OAAO,MAAM,EAAE;AACnD,aAAS;AACT,uBAAmB;AACnB,YAAQ,KAAK,cAAc;;;AAG/B,MAAI,QAAQ,eAAe,YAAY,aAAa,QAAQ,aAAa,MAAM,EAAE;AAC/E,YAAS;AACT,sBAAmB;AACnB,WAAQ,KAAK,oBAAoB;;AAEnC,MAAI,QAAQ,QAAQ,YAAY,aAAa,QAAQ,MAAM,MAAM,EAAE;AACjE,YAAS;AACT,sBAAmB;AACnB,WAAQ,KAAK,aAAa;;AAE5B,MAAI,QAAQ,UAAU,WAAW,QAAQ,QAAQ;AAC/C,YAAS;AACT,sBAAmB;AACnB,WAAQ,KAAK,gBAAgB;;AAE/B,MAAI,eAAe;AACjB,YAAS;AACT,WAAQ,KAAK,sBAAsB;;AAErC,MAAI,SAAS;AACX,YAAS;AACT,WAAQ,KAAK,UAAU;;AAEzB,MAAI,SAAS;AACX,YAAS;AACT,WAAQ,KAAK,UAAU;;AAEzB,MAAI,oBAAoB,EACtB,QAAO;AAGT,SAAO;GACL;GACA;GACA,WAAW;IACT,SAAS,QAAQ,QAAQ,aAAa;IACtC,IAAI,QAAQ;IACZ,WAAW,QAAQ,aAAa,QAAQ,IAAI;IAC5C;IACA;IACA;IACA;IACA;IACA,aAAa,YAAY,MAAM,GAAG,IAAI;IACtC;IACA;IACA,MAAM;KACJ,GAAG,KAAK;KACR,GAAG,KAAK;KACR,OAAO,KAAK;KACZ,QAAQ,KAAK;KACd;IACF;GACF;GACD,CACD,QAAQ,UAA8C,UAAU,QAAQ,MAAM,QAAQ,EAAE,CACxF,MAAM,MAAM,UAAU,MAAM,QAAQ,KAAK,MAAM,CAC/C,MAAM,GAAG,MAAM;AAElB,QAAO;EACL,iBAAiB,WAAW;EAC5B;EACD;;AAGH,eAAe,YAAY,QAAgD;CAEzE,MAAM,UAAU,MAAM,cAAc,OAAQ;AAE5C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,SAAQ,eAAe;EAAE,UAAU;EAAU,OAAO;EAAU,CAAC;CAE/D,MAAM,OAAO,QAAQ,uBAAuB;CAC5C,MAAM,IAAI,KAAK,OAAO,KAAK,QAAQ;CACnC,MAAM,IAAI,KAAK,MAAM,KAAK,SAAS;AAEnC,SAAQ,cAAc,IAAI,WAAW,cAAc;EAAE,SAAS;EAAM,SAAS;EAAG,SAAS;EAAG,CAAC,CAAC;AAC9F,SAAQ,cAAc,IAAI,WAAW,aAAa;EAAE,SAAS;EAAM,SAAS;EAAG,SAAS;EAAG,CAAC,CAAC;AAC7F,SAAQ,cAAc,IAAI,WAAW,aAAa;EAAE,SAAS;EAAM,SAAS;EAAG,SAAS;EAAG,CAAC,CAAC;;AAG/F,eAAe,aAAa,QAAgD;CAC1E,MAAM,UAAU;CAChB,MAAM,QAAQ,OAAO;CACrB,MAAM,UAAU,MAAM,cAAc,QAAQ;AAE5C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,KAAI,EAAE,mBAAmB,mBACvB,OAAM,IAAI,MAAM,kCAAkC;CAGpD,MAAM,SAAS,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;AAErD,MAAK,MAAM,UAAU,QAAQ,QAC3B,QAAO,WAAW,OAAO,SAAS,OAAO,MAAM,IAAI,OAAO,SAAS,OAAO,KAAK;AAGjF,SAAQ,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,MAAM,CAAC,CAAC;AAC5D,SAAQ,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,MAAM,CAAC,CAAC;;AAG/D,eAAe,WAAW,QAAgD;CACxE,MAAM,gBAAgB,OAAO;CAC7B,MAAM,gBAAgB,OAAO;CAE7B,MAAM,gBAAgB,MAAM,cAAc,cAAc;CACxD,MAAM,gBAAgB,MAAM,cAAc,cAAc;AAExD,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,2BAA2B;AAG7C,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,2BAA2B;CAG7C,MAAM,aAAa,cAAc,uBAAuB;CACxD,MAAM,aAAa,cAAc,uBAAuB;CAExD,MAAM,UAAU,WAAW,OAAO,WAAW,QAAQ;CACrD,MAAM,UAAU,WAAW,MAAM,WAAW,SAAS;CACrD,MAAM,UAAU,WAAW,OAAO,WAAW,QAAQ;CACrD,MAAM,UAAU,WAAW,MAAM,WAAW,SAAS;CACrD,MAAM,eAAe,IAAI,cAAc;AAEvC,eAAc,cAAc,IAAI,WAAW,aAAa;EAAE,SAAS;EAAM,SAAS;EAAS,SAAS;EAAS,CAAC,CAAC;AAC/G,eAAc,cACZ,IAAI,UAAU,aAAa;EACzB,SAAS;EACT,SAAS;EACT,SAAS;EACT;EACD,CAAC,CACH;AAED,eAAc,cACZ,IAAI,UAAU,aAAa;EACzB,SAAS;EACT,SAAS;EACT,SAAS;EACT;EACD,CAAC,CACH;AACD,eAAc,cACZ,IAAI,UAAU,YAAY;EACxB,SAAS;EACT,SAAS;EACT,SAAS;EACT;EACD,CAAC,CACH;AACD,eAAc,cACZ,IAAI,UAAU,QAAQ;EACpB,SAAS;EACT,SAAS;EACT,SAAS;EACT;EACD,CAAC,CACH;AAED,eAAc,cACZ,IAAI,UAAU,WAAW;EACvB,SAAS;EACT,SAAS;EACT,SAAS;EACT;EACD,CAAC,CACH;AACD,eAAc,cAAc,IAAI,WAAW,WAAW;EAAE,SAAS;EAAM,SAAS;EAAS,SAAS;EAAS,CAAC,CAAC;;AAG/G,eAAe,eAAe,QAAgD;CAC5E,MAAM,MAAM,OAAO;CACnB,MAAM,YAAY,OAAO;CAEzB,MAAM,YAA+B;EACnC;EACA,SAAS;EACT,SAAS,WAAW,SAAS,UAAU,IAAI,WAAW,SAAS,OAAO;EACtE,UAAU,WAAW,SAAS,QAAQ;EACtC,QAAQ,WAAW,SAAS,MAAM;EAClC,SAAS,WAAW,SAAS,OAAO,IAAI,WAAW,SAAS,UAAU;EACvE;CAED,MAAM,gBAAgB,SAAS,iBAAiB,SAAS;AACzD,eAAc,cAAc,IAAI,cAAc,WAAW,UAAU,CAAC;AACpE,eAAc,cAAc,IAAI,cAAc,YAAY,UAAU,CAAC;AACrE,eAAc,cAAc,IAAI,cAAc,SAAS,UAAU,CAAC;;AAGpE,eAAe,cAAc,QAAgD;CAC3E,MAAM,WAAW,OAAO;CACxB,MAAM,OAAO,OAAO;CACpB,MAAM,QAAS,OAAO,SAAoB;CAC1C,MAAM,UAAW,OAAO,WAAsB;CAE9C,MAAM,YAAY,KAAK,KAAK;AAE5B,QAAO,KAAK,KAAK,GAAG,YAAY,SAAS;AACvC,MAAI,UAAU;GACZ,MAAM,UAAU,MAAM,cAAc,EAAE,UAAU,CAAC;AACjD,OAAI,UAAU,aAAa,WAAW,UAAU,QAAQ,CACtD;AAEF,OAAI,UAAU,aAAa,CAAC,WAAW,CAAC,UAAU,QAAQ,EACxD;AAEF,OAAI,UAAU,cAAc,QAC1B;AAEF,OAAI,UAAU,cAAc,CAAC,QAC3B;;AAIJ,MAAI;OACY,SAAS,KAAK,aAAa,SAAS,KAAK,CAErD;;AAIJ,QAAM,IAAI,SAAS,YAAY,WAAW,SAAS,IAAI,CAAC;;AAG1D,OAAM,IAAI,MAAM,iCAAiC,QAAQ,IAAI;;AAG/D,eAAe,sBAAsB,QAAmD;CAEtF,MAAM,UAAU,MAAM,cAAc,OAAQ;AAE5C,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,oBAAoB;AAGtC,SAAQ,eAAe;EAAE,UAAU;EAAW,OAAO;EAAU,CAAC;AAEhE,OAAM,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;CAEvD,MAAM,OAAO,QAAQ,uBAAuB;AAE5C,QAAO;EACL,MAAM;GAAE,GAAG,KAAK;GAAG,GAAG,KAAK;GAAG,OAAO,KAAK;GAAO,QAAQ,KAAK;GAAQ;EACtE,SAAS,QAAQ,QAAQ,aAAa;EACtC,aACE,mBAAmB,oBACnB,mBAAmB,uBACnB,mBAAmB,qBACnB,QAAQ,aAAa,kBAAkB,IACvC,QAAQ,aAAa,WAAW,KAAK;EACxC;;AAGH,SAAS,UAAU,SAA2B;CAC5C,MAAM,QAAQ,OAAO,iBAAiB,QAAQ;AAC9C,QAAO,MAAM,YAAY,UAAU,MAAM,eAAe,YAAY,MAAM,YAAY"}
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./streamable-http-u32a2By0.cjs`);let t=require(`zod`),n=require(`@agimon-ai/foundation-validator`),r=require(`@modelcontextprotocol/sdk/server/index.js`),i=require(`@modelcontextprotocol/sdk/types.js`),a=require(`liquidjs`);function o(e){return typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:JSON.stringify(e)}function s(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=o(r));return Object.keys(t).length>0?t:void 0}function c(){let t=new e.g({serviceName:`browse-tool-mcp`});return{debug(e,n){t.log(`debug`,e,{attributes:s(n)})},info(e,n){t.log(`info`,e,{attributes:s(n)})},warn(e,n){t.log(`warn`,e,{attributes:s(n)})},error(e,n){t.log(`error`,e,{attributes:s(n)})},runInSpan(e,n,r){return t.runInSpan(e,{attributes:s(n)},r)}}}var l=class extends Error{code=`UNKNOWN_TOOL`;recovery=`Use ListTools to see available tools.`;availableTools;constructor(e,t,n){super(`Unknown tool: ${e}. Available tools: ${t.slice(0,5).join(`, `)}${t.length>5?`, ... (${t.length} total)`:``}. Use ListTools to see all available tools.`,n),this.name=`UnknownToolError`,this.availableTools=t}},u=class extends Error{code=`TOOL_EXECUTION_ERROR`;recovery;toolName;constructor(e,t,n){super(`Tool execution failed for '${e}': ${t}`,n),this.name=`ToolExecutionError`,this.toolName=e,this.recovery=n?.recovery??`Check tool inputs and try again.`}};function d(e,t){let n=e instanceof Error?e.message:`Unknown error occurred`,r={error:{code:e instanceof Error&&`code`in e?e.code:`TOOL_EXECUTION_ERROR`,message:n,toolName:t,recovery:e instanceof Error&&`recovery`in e?e.recovery:`Check tool inputs and try again.`}};return{content:[{type:`text`,text:JSON.stringify(r,null,2)}],isError:!0}}function f(a){let o=a?.container??e.r,s=a?.logger??c(),f=new r.Server({name:`browse-tool`,version:`0.1.0`},{capabilities:{tools:{}}}),p=o.getAll(e.M.Tool),m=new Map;for(let e of p){let t=e.getDefinition();m.set(t.name,e)}return s.info(`MCP server initialized`,{toolCount:p.length}),f.setRequestHandler(i.ListToolsRequestSchema,async()=>{let e=async()=>(s.debug(`ListTools request received`),{tools:p.map(e=>e.getDefinition())});return await(s.runInSpan?.(`mcp.server.list_tools`,{"mcp.service":`browse-tool`},e)??e())}),f.setRequestHandler(i.CallToolRequestSchema,async e=>{let{name:r,arguments:i}=e.params,a=async()=>{s.debug(`Tool call received`,{toolName:r,timestamp:new Date().toISOString()});let e=m.get(r);if(!e){let e=Array.from(m.keys());throw s.warn(`Unknown tool requested`,{toolName:r,availableTools:e,timestamp:new Date().toISOString()}),new l(r,e)}let a=(0,n.coerceArgs)(i??{},e.getInputSchema());try{let t=e.getInputSchema().parse(a);return await e.execute(t)}catch(i){if(i instanceof t.z.ZodError)return s.warn(`Tool input validation failed`,{toolName:r,timestamp:new Date().toISOString()}),{content:[{type:`text`,text:(0,n.formatZodError)(i,{schemaName:r,schema:e.getInputSchema()})}],isError:!0};let a=i instanceof u?i:new u(r,i instanceof Error?i.message:String(i),{cause:i});return s.error(`Tool execution failed`,{toolName:r,error:a.message,code:a.code,timestamp:new Date().toISOString()}),d(a,r)}};return await(s.runInSpan?.(`mcp.server.call_tool`,{"mcp.service":`browse-tool`,"mcp.tool.name":r},a)??a())}),f}var p='Create a browse-tool custom tool folder for use with `browse-tool mcp-serve --custom-tools <dir>`.\n\nGoal: {{ toolGoal }}\nPreferred tool name: {{ preferredToolName }}\nPage context: {{ pageContext }}\n\nRequirements:\n- Produce a `tools.yaml` file with a top-level `tools` array.\n- Each tool entry must include `name`, `description`, `script`, `capabilities`, and `inputSchema`.\n- Each tool entry may optionally include `suggestionActions` as a short text string describing the recommended next step after the tool succeeds.\n- `inputSchema` must be JSON Schema with `type: object`.\n- `inputSchema` must define at least one execution target field: `pageId` and/or `browserId`, each as `type: string` when present.\n- The script file must be `.ts` and export a named `run` function with the shape `export const run = async ({ page, browser, input, logger }) => { ... }`.\n- The `run` export runs in Node.js, not inside the page.\n- Use the provided `page` object for browser interaction. It will be a Playwright page in playwright mode or an extension page proxy in extension mode.\n- Use the provided `browser` helper when the tool needs to list pages, open a new page, or work from `browserId` instead of an existing `pageId`.\n- `browser` is not a raw Playwright browser. It exposes `browserId`, `mode`, `listPages()`, `getPage(pageId)`, `getCurrentPage()`, and `newPage({ url?, setAsCurrent? })`.\n- Use the provided `logger` object for instrumentation. It exposes `trace`, `debug`, `info`, `warn`, `error`, and `fatal`, and logs automatically attach to the active custom-tool telemetry context.\n- The logger also exposes `getTraceContext()` so a tool can return the active `traceId` and `spanId` when needed for downstream log inspection.\n- If you need DOM access, call `page.evaluate(...)` from the `run` export instead of assuming browser globals are available at module scope.\n- Keep the script self-contained and avoid relative imports.\n- Return either a plain object, a string, or an MCP-style `CallToolResult`.\n- Prefer read-only behavior unless the goal explicitly requires mutation.\n\nOutput format:\n- Show the full `tools.yaml` content.\n- Show the full `{{ preferredToolName }}.ts` content.\n- If the tool needs additional inputs beyond `pageId` or `browserId`, define them in `inputSchema` and read them from `input`.\n- Filesystem access is allowed because the script runs in Node.js.\n\nExample `tools.yaml` shape:\n```yaml\ntools:\n - name: get_post\n description: Get the current post from the open feed page\n script: get_post.ts\n suggestionActions: Open the author profile and review whether the post is worth engaging with\n capabilities:\n readOnlyHint: true\n openWorldHint: false\n inputSchema:\n type: object\n properties:\n pageId:\n type: string\n browserId:\n type: string\n selector:\n type: string\n required:\n - pageId\n```\n\nExample script shape:\n```ts\nexport const run = async ({ page, browser, input, logger }) => {\n const traceContext = logger.getTraceContext();\n logger.info("reading post", { attributes: { selector: input.selector ?? "body", browserId: browser.browserId } });\n const selector = input.selector ?? "body";\n const text = await page.evaluate((currentSelector) => {\n return document.querySelector(currentSelector)?.textContent ?? "";\n }, selector);\n return {\n pageUrl: page.url(),\n traceContext,\n text,\n };\n};\n```\n';const m={name:`custom_script_authoring`,description:`Generate a browse-tool custom tool folder with tools.yaml and TypeScript scripts.`,arguments:[{name:`toolGoal`,description:`What the custom tool should do on the page`,required:!0},{name:`toolName`,description:`Preferred snake_case tool name`,required:!1},{name:`pageContext`,description:`Optional context about the target page or workflow`,required:!1}]},h=new a.Liquid;function g(e){let t=e.toolName?.trim()||`custom_page_tool`,n=e.pageContext?.trim()||`No extra page context provided.`;return[{role:`user`,content:{type:`text`,text:h.parseAndRenderSync(p,{toolGoal:e.toolGoal,preferredToolName:t,pageContext:n})}}]}exports.PLAYWRIGHT_TYPES=e.M,exports.StdioTransportHandler=e.n,exports.StreamableHttpTransportHandler=e.t,exports.ToolExecutionError=u,exports.UnknownToolError=l,exports.container=e.r,exports.createContainer=e.i,exports.createServer=f,exports.customScriptAuthoringPrompt=m,exports.generateCustomScriptAuthoringPrompt=g;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./streamable-http-BLUtoU2x.cjs`);let t=require(`zod`),n=require(`@agimon-ai/foundation-validator`),r=require(`@modelcontextprotocol/sdk/server/index.js`),i=require(`@modelcontextprotocol/sdk/types.js`),a=require(`liquidjs`);function o(e){return typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:JSON.stringify(e)}function s(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=o(r));return Object.keys(t).length>0?t:void 0}function c(){let t=new e.g({serviceName:`browse-tool-mcp`});return{debug(e,n){t.log(`debug`,e,{attributes:s(n)})},info(e,n){t.log(`info`,e,{attributes:s(n)})},warn(e,n){t.log(`warn`,e,{attributes:s(n)})},error(e,n){t.log(`error`,e,{attributes:s(n)})},runInSpan(e,n,r){return t.runInSpan(e,{attributes:s(n)},r)}}}var l=class extends Error{code=`UNKNOWN_TOOL`;recovery=`Use ListTools to see available tools.`;availableTools;constructor(e,t,n){super(`Unknown tool: ${e}. Available tools: ${t.slice(0,5).join(`, `)}${t.length>5?`, ... (${t.length} total)`:``}. Use ListTools to see all available tools.`,n),this.name=`UnknownToolError`,this.availableTools=t}},u=class extends Error{code=`TOOL_EXECUTION_ERROR`;recovery;toolName;constructor(e,t,n){super(`Tool execution failed for '${e}': ${t}`,n),this.name=`ToolExecutionError`,this.toolName=e,this.recovery=n?.recovery??`Check tool inputs and try again.`}};function d(e,t){let n=e instanceof Error?e.message:`Unknown error occurred`,r={error:{code:e instanceof Error&&`code`in e?e.code:`TOOL_EXECUTION_ERROR`,message:n,toolName:t,recovery:e instanceof Error&&`recovery`in e?e.recovery:`Check tool inputs and try again.`}};return{content:[{type:`text`,text:JSON.stringify(r,null,2)}],isError:!0}}function f(a){let o=a?.container??e.r,s=a?.logger??c(),f=new r.Server({name:`browse-tool`,version:`0.1.0`},{capabilities:{tools:{}}}),p=o.getAll(e.M.Tool),m=new Map;for(let e of p){let t=e.getDefinition();m.set(t.name,e)}return s.info(`MCP server initialized`,{toolCount:p.length}),f.setRequestHandler(i.ListToolsRequestSchema,async()=>{let e=async()=>(s.debug(`ListTools request received`),{tools:p.map(e=>e.getDefinition())});return await(s.runInSpan?.(`mcp.server.list_tools`,{"mcp.service":`browse-tool`},e)??e())}),f.setRequestHandler(i.CallToolRequestSchema,async e=>{let{name:r,arguments:i}=e.params,a=async()=>{s.debug(`Tool call received`,{toolName:r,timestamp:new Date().toISOString()});let e=m.get(r);if(!e){let e=Array.from(m.keys());throw s.warn(`Unknown tool requested`,{toolName:r,availableTools:e,timestamp:new Date().toISOString()}),new l(r,e)}let a=(0,n.coerceArgs)(i??{},e.getInputSchema());try{let t=e.getInputSchema().parse(a);return await e.execute(t)}catch(i){if(i instanceof t.z.ZodError)return s.warn(`Tool input validation failed`,{toolName:r,timestamp:new Date().toISOString()}),{content:[{type:`text`,text:(0,n.formatZodError)(i,{schemaName:r,schema:e.getInputSchema()})}],isError:!0};let a=i instanceof u?i:new u(r,i instanceof Error?i.message:String(i),{cause:i});return s.error(`Tool execution failed`,{toolName:r,error:a.message,code:a.code,timestamp:new Date().toISOString()}),d(a,r)}};return await(s.runInSpan?.(`mcp.server.call_tool`,{"mcp.service":`browse-tool`,"mcp.tool.name":r},a)??a())}),f}var p='Create a browse-tool custom tool folder for use with `browse-tool mcp-serve --custom-tools <dir>`.\n\nGoal: {{ toolGoal }}\nPreferred tool name: {{ preferredToolName }}\nPage context: {{ pageContext }}\n\nRequirements:\n- Produce a `tools.yaml` file with a top-level `tools` array.\n- Each tool entry must include `name`, `description`, `script`, `capabilities`, and `inputSchema`.\n- Each tool entry may optionally include `suggestionActions` as a short text string describing the recommended next step after the tool succeeds.\n- `inputSchema` must be JSON Schema with `type: object`.\n- `inputSchema` must define at least one execution target field: `pageId` and/or `browserId`, each as `type: string` when present.\n- The script file must be `.ts` and export a named `run` function with the shape `export const run = async ({ page, browser, input, logger }) => { ... }`.\n- The `run` export runs in Node.js, not inside the page.\n- Use the provided `page` object for browser interaction. It will be a Playwright page in playwright mode or an extension page proxy in extension mode.\n- Use the provided `browser` helper when the tool needs to list pages, open a new page, or work from `browserId` instead of an existing `pageId`.\n- `browser` is not a raw Playwright browser. It exposes `browserId`, `mode`, `listPages()`, `getPage(pageId)`, `getCurrentPage()`, and `newPage({ url?, setAsCurrent? })`.\n- Use the provided `logger` object for instrumentation. It exposes `trace`, `debug`, `info`, `warn`, `error`, and `fatal`, and logs automatically attach to the active custom-tool telemetry context.\n- The logger also exposes `getTraceContext()` so a tool can return the active `traceId` and `spanId` when needed for downstream log inspection.\n- If you need DOM access, call `page.evaluate(...)` from the `run` export instead of assuming browser globals are available at module scope.\n- Keep the script self-contained and avoid relative imports.\n- Return either a plain object, a string, or an MCP-style `CallToolResult`.\n- Prefer read-only behavior unless the goal explicitly requires mutation.\n\nOutput format:\n- Show the full `tools.yaml` content.\n- Show the full `{{ preferredToolName }}.ts` content.\n- If the tool needs additional inputs beyond `pageId` or `browserId`, define them in `inputSchema` and read them from `input`.\n- Filesystem access is allowed because the script runs in Node.js.\n\nExample `tools.yaml` shape:\n```yaml\ntools:\n - name: get_post\n description: Get the current post from the open feed page\n script: get_post.ts\n suggestionActions: Open the author profile and review whether the post is worth engaging with\n capabilities:\n readOnlyHint: true\n openWorldHint: false\n inputSchema:\n type: object\n properties:\n pageId:\n type: string\n browserId:\n type: string\n selector:\n type: string\n required:\n - pageId\n```\n\nExample script shape:\n```ts\nexport const run = async ({ page, browser, input, logger }) => {\n const traceContext = logger.getTraceContext();\n logger.info("reading post", { attributes: { selector: input.selector ?? "body", browserId: browser.browserId } });\n const selector = input.selector ?? "body";\n const text = await page.evaluate((currentSelector) => {\n return document.querySelector(currentSelector)?.textContent ?? "";\n }, selector);\n return {\n pageUrl: page.url(),\n traceContext,\n text,\n };\n};\n```\n';const m={name:`custom_script_authoring`,description:`Generate a browse-tool custom tool folder with tools.yaml and TypeScript scripts.`,arguments:[{name:`toolGoal`,description:`What the custom tool should do on the page`,required:!0},{name:`toolName`,description:`Preferred snake_case tool name`,required:!1},{name:`pageContext`,description:`Optional context about the target page or workflow`,required:!1}]},h=new a.Liquid;function g(e){let t=e.toolName?.trim()||`custom_page_tool`,n=e.pageContext?.trim()||`No extra page context provided.`;return[{role:`user`,content:{type:`text`,text:h.parseAndRenderSync(p,{toolGoal:e.toolGoal,preferredToolName:t,pageContext:n})}}]}exports.PLAYWRIGHT_TYPES=e.M,exports.StdioTransportHandler=e.n,exports.StreamableHttpTransportHandler=e.t,exports.ToolExecutionError=u,exports.UnknownToolError=l,exports.container=e.r,exports.createContainer=e.i,exports.createServer=f,exports.customScriptAuthoringPrompt=m,exports.generateCustomScriptAuthoringPrompt=g;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{M as e,g as t,i as n,n as r,r as i,t as a}from"./streamable-http-BPEGdTS4.mjs";import{z as o}from"zod";import{coerceArgs as s,formatZodError as c}from"@agimon-ai/foundation-validator";import{Server as l}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as u,ListToolsRequestSchema as d}from"@modelcontextprotocol/sdk/types.js";import{Liquid as f}from"liquidjs";function p(e){return typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:JSON.stringify(e)}function m(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=p(r));return Object.keys(t).length>0?t:void 0}function h(){let e=new t({serviceName:`browse-tool-mcp`});return{debug(t,n){e.log(`debug`,t,{attributes:m(n)})},info(t,n){e.log(`info`,t,{attributes:m(n)})},warn(t,n){e.log(`warn`,t,{attributes:m(n)})},error(t,n){e.log(`error`,t,{attributes:m(n)})},runInSpan(t,n,r){return e.runInSpan(t,{attributes:m(n)},r)}}}var g=class extends Error{code=`UNKNOWN_TOOL`;recovery=`Use ListTools to see available tools.`;availableTools;constructor(e,t,n){super(`Unknown tool: ${e}. Available tools: ${t.slice(0,5).join(`, `)}${t.length>5?`, ... (${t.length} total)`:``}. Use ListTools to see all available tools.`,n),this.name=`UnknownToolError`,this.availableTools=t}},_=class extends Error{code=`TOOL_EXECUTION_ERROR`;recovery;toolName;constructor(e,t,n){super(`Tool execution failed for '${e}': ${t}`,n),this.name=`ToolExecutionError`,this.toolName=e,this.recovery=n?.recovery??`Check tool inputs and try again.`}};function v(e,t){let n=e instanceof Error?e.message:`Unknown error occurred`,r={error:{code:e instanceof Error&&`code`in e?e.code:`TOOL_EXECUTION_ERROR`,message:n,toolName:t,recovery:e instanceof Error&&`recovery`in e?e.recovery:`Check tool inputs and try again.`}};return{content:[{type:`text`,text:JSON.stringify(r,null,2)}],isError:!0}}function y(t){let n=t?.container??i,r=t?.logger??h(),a=new l({name:`browse-tool`,version:`0.1.0`},{capabilities:{tools:{}}}),f=n.getAll(e.Tool),p=new Map;for(let e of f){let t=e.getDefinition();p.set(t.name,e)}return r.info(`MCP server initialized`,{toolCount:f.length}),a.setRequestHandler(d,async()=>{let e=async()=>(r.debug(`ListTools request received`),{tools:f.map(e=>e.getDefinition())});return await(r.runInSpan?.(`mcp.server.list_tools`,{"mcp.service":`browse-tool`},e)??e())}),a.setRequestHandler(u,async e=>{let{name:t,arguments:n}=e.params,i=async()=>{r.debug(`Tool call received`,{toolName:t,timestamp:new Date().toISOString()});let e=p.get(t);if(!e){let e=Array.from(p.keys());throw r.warn(`Unknown tool requested`,{toolName:t,availableTools:e,timestamp:new Date().toISOString()}),new g(t,e)}let i=s(n??{},e.getInputSchema());try{let t=e.getInputSchema().parse(i);return await e.execute(t)}catch(n){if(n instanceof o.ZodError)return r.warn(`Tool input validation failed`,{toolName:t,timestamp:new Date().toISOString()}),{content:[{type:`text`,text:c(n,{schemaName:t,schema:e.getInputSchema()})}],isError:!0};let i=n instanceof _?n:new _(t,n instanceof Error?n.message:String(n),{cause:n});return r.error(`Tool execution failed`,{toolName:t,error:i.message,code:i.code,timestamp:new Date().toISOString()}),v(i,t)}};return await(r.runInSpan?.(`mcp.server.call_tool`,{"mcp.service":`browse-tool`,"mcp.tool.name":t},i)??i())}),a}var b='Create a browse-tool custom tool folder for use with `browse-tool mcp-serve --custom-tools <dir>`.\n\nGoal: {{ toolGoal }}\nPreferred tool name: {{ preferredToolName }}\nPage context: {{ pageContext }}\n\nRequirements:\n- Produce a `tools.yaml` file with a top-level `tools` array.\n- Each tool entry must include `name`, `description`, `script`, `capabilities`, and `inputSchema`.\n- Each tool entry may optionally include `suggestionActions` as a short text string describing the recommended next step after the tool succeeds.\n- `inputSchema` must be JSON Schema with `type: object`.\n- `inputSchema` must define at least one execution target field: `pageId` and/or `browserId`, each as `type: string` when present.\n- The script file must be `.ts` and export a named `run` function with the shape `export const run = async ({ page, browser, input, logger }) => { ... }`.\n- The `run` export runs in Node.js, not inside the page.\n- Use the provided `page` object for browser interaction. It will be a Playwright page in playwright mode or an extension page proxy in extension mode.\n- Use the provided `browser` helper when the tool needs to list pages, open a new page, or work from `browserId` instead of an existing `pageId`.\n- `browser` is not a raw Playwright browser. It exposes `browserId`, `mode`, `listPages()`, `getPage(pageId)`, `getCurrentPage()`, and `newPage({ url?, setAsCurrent? })`.\n- Use the provided `logger` object for instrumentation. It exposes `trace`, `debug`, `info`, `warn`, `error`, and `fatal`, and logs automatically attach to the active custom-tool telemetry context.\n- The logger also exposes `getTraceContext()` so a tool can return the active `traceId` and `spanId` when needed for downstream log inspection.\n- If you need DOM access, call `page.evaluate(...)` from the `run` export instead of assuming browser globals are available at module scope.\n- Keep the script self-contained and avoid relative imports.\n- Return either a plain object, a string, or an MCP-style `CallToolResult`.\n- Prefer read-only behavior unless the goal explicitly requires mutation.\n\nOutput format:\n- Show the full `tools.yaml` content.\n- Show the full `{{ preferredToolName }}.ts` content.\n- If the tool needs additional inputs beyond `pageId` or `browserId`, define them in `inputSchema` and read them from `input`.\n- Filesystem access is allowed because the script runs in Node.js.\n\nExample `tools.yaml` shape:\n```yaml\ntools:\n - name: get_post\n description: Get the current post from the open feed page\n script: get_post.ts\n suggestionActions: Open the author profile and review whether the post is worth engaging with\n capabilities:\n readOnlyHint: true\n openWorldHint: false\n inputSchema:\n type: object\n properties:\n pageId:\n type: string\n browserId:\n type: string\n selector:\n type: string\n required:\n - pageId\n```\n\nExample script shape:\n```ts\nexport const run = async ({ page, browser, input, logger }) => {\n const traceContext = logger.getTraceContext();\n logger.info("reading post", { attributes: { selector: input.selector ?? "body", browserId: browser.browserId } });\n const selector = input.selector ?? "body";\n const text = await page.evaluate((currentSelector) => {\n return document.querySelector(currentSelector)?.textContent ?? "";\n }, selector);\n return {\n pageUrl: page.url(),\n traceContext,\n text,\n };\n};\n```\n';const x={name:`custom_script_authoring`,description:`Generate a browse-tool custom tool folder with tools.yaml and TypeScript scripts.`,arguments:[{name:`toolGoal`,description:`What the custom tool should do on the page`,required:!0},{name:`toolName`,description:`Preferred snake_case tool name`,required:!1},{name:`pageContext`,description:`Optional context about the target page or workflow`,required:!1}]},S=new f;function C(e){let t=e.toolName?.trim()||`custom_page_tool`,n=e.pageContext?.trim()||`No extra page context provided.`;return[{role:`user`,content:{type:`text`,text:S.parseAndRenderSync(b,{toolGoal:e.toolGoal,preferredToolName:t,pageContext:n})}}]}export{e as PLAYWRIGHT_TYPES,r as StdioTransportHandler,a as StreamableHttpTransportHandler,_ as ToolExecutionError,g as UnknownToolError,i as container,n as createContainer,y as createServer,x as customScriptAuthoringPrompt,C as generateCustomScriptAuthoringPrompt};
1
+ import{M as e,g as t,i as n,n as r,r as i,t as a}from"./streamable-http-AtkbCdt-.mjs";import{z as o}from"zod";import{coerceArgs as s,formatZodError as c}from"@agimon-ai/foundation-validator";import{Server as l}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as u,ListToolsRequestSchema as d}from"@modelcontextprotocol/sdk/types.js";import{Liquid as f}from"liquidjs";function p(e){return typeof e==`string`||typeof e==`number`||typeof e==`boolean`?e:JSON.stringify(e)}function m(e){if(!e)return;let t={};for(let[n,r]of Object.entries(e))r!=null&&(t[n]=p(r));return Object.keys(t).length>0?t:void 0}function h(){let e=new t({serviceName:`browse-tool-mcp`});return{debug(t,n){e.log(`debug`,t,{attributes:m(n)})},info(t,n){e.log(`info`,t,{attributes:m(n)})},warn(t,n){e.log(`warn`,t,{attributes:m(n)})},error(t,n){e.log(`error`,t,{attributes:m(n)})},runInSpan(t,n,r){return e.runInSpan(t,{attributes:m(n)},r)}}}var g=class extends Error{code=`UNKNOWN_TOOL`;recovery=`Use ListTools to see available tools.`;availableTools;constructor(e,t,n){super(`Unknown tool: ${e}. Available tools: ${t.slice(0,5).join(`, `)}${t.length>5?`, ... (${t.length} total)`:``}. Use ListTools to see all available tools.`,n),this.name=`UnknownToolError`,this.availableTools=t}},_=class extends Error{code=`TOOL_EXECUTION_ERROR`;recovery;toolName;constructor(e,t,n){super(`Tool execution failed for '${e}': ${t}`,n),this.name=`ToolExecutionError`,this.toolName=e,this.recovery=n?.recovery??`Check tool inputs and try again.`}};function v(e,t){let n=e instanceof Error?e.message:`Unknown error occurred`,r={error:{code:e instanceof Error&&`code`in e?e.code:`TOOL_EXECUTION_ERROR`,message:n,toolName:t,recovery:e instanceof Error&&`recovery`in e?e.recovery:`Check tool inputs and try again.`}};return{content:[{type:`text`,text:JSON.stringify(r,null,2)}],isError:!0}}function y(t){let n=t?.container??i,r=t?.logger??h(),a=new l({name:`browse-tool`,version:`0.1.0`},{capabilities:{tools:{}}}),f=n.getAll(e.Tool),p=new Map;for(let e of f){let t=e.getDefinition();p.set(t.name,e)}return r.info(`MCP server initialized`,{toolCount:f.length}),a.setRequestHandler(d,async()=>{let e=async()=>(r.debug(`ListTools request received`),{tools:f.map(e=>e.getDefinition())});return await(r.runInSpan?.(`mcp.server.list_tools`,{"mcp.service":`browse-tool`},e)??e())}),a.setRequestHandler(u,async e=>{let{name:t,arguments:n}=e.params,i=async()=>{r.debug(`Tool call received`,{toolName:t,timestamp:new Date().toISOString()});let e=p.get(t);if(!e){let e=Array.from(p.keys());throw r.warn(`Unknown tool requested`,{toolName:t,availableTools:e,timestamp:new Date().toISOString()}),new g(t,e)}let i=s(n??{},e.getInputSchema());try{let t=e.getInputSchema().parse(i);return await e.execute(t)}catch(n){if(n instanceof o.ZodError)return r.warn(`Tool input validation failed`,{toolName:t,timestamp:new Date().toISOString()}),{content:[{type:`text`,text:c(n,{schemaName:t,schema:e.getInputSchema()})}],isError:!0};let i=n instanceof _?n:new _(t,n instanceof Error?n.message:String(n),{cause:n});return r.error(`Tool execution failed`,{toolName:t,error:i.message,code:i.code,timestamp:new Date().toISOString()}),v(i,t)}};return await(r.runInSpan?.(`mcp.server.call_tool`,{"mcp.service":`browse-tool`,"mcp.tool.name":t},i)??i())}),a}var b='Create a browse-tool custom tool folder for use with `browse-tool mcp-serve --custom-tools <dir>`.\n\nGoal: {{ toolGoal }}\nPreferred tool name: {{ preferredToolName }}\nPage context: {{ pageContext }}\n\nRequirements:\n- Produce a `tools.yaml` file with a top-level `tools` array.\n- Each tool entry must include `name`, `description`, `script`, `capabilities`, and `inputSchema`.\n- Each tool entry may optionally include `suggestionActions` as a short text string describing the recommended next step after the tool succeeds.\n- `inputSchema` must be JSON Schema with `type: object`.\n- `inputSchema` must define at least one execution target field: `pageId` and/or `browserId`, each as `type: string` when present.\n- The script file must be `.ts` and export a named `run` function with the shape `export const run = async ({ page, browser, input, logger }) => { ... }`.\n- The `run` export runs in Node.js, not inside the page.\n- Use the provided `page` object for browser interaction. It will be a Playwright page in playwright mode or an extension page proxy in extension mode.\n- Use the provided `browser` helper when the tool needs to list pages, open a new page, or work from `browserId` instead of an existing `pageId`.\n- `browser` is not a raw Playwright browser. It exposes `browserId`, `mode`, `listPages()`, `getPage(pageId)`, `getCurrentPage()`, and `newPage({ url?, setAsCurrent? })`.\n- Use the provided `logger` object for instrumentation. It exposes `trace`, `debug`, `info`, `warn`, `error`, and `fatal`, and logs automatically attach to the active custom-tool telemetry context.\n- The logger also exposes `getTraceContext()` so a tool can return the active `traceId` and `spanId` when needed for downstream log inspection.\n- If you need DOM access, call `page.evaluate(...)` from the `run` export instead of assuming browser globals are available at module scope.\n- Keep the script self-contained and avoid relative imports.\n- Return either a plain object, a string, or an MCP-style `CallToolResult`.\n- Prefer read-only behavior unless the goal explicitly requires mutation.\n\nOutput format:\n- Show the full `tools.yaml` content.\n- Show the full `{{ preferredToolName }}.ts` content.\n- If the tool needs additional inputs beyond `pageId` or `browserId`, define them in `inputSchema` and read them from `input`.\n- Filesystem access is allowed because the script runs in Node.js.\n\nExample `tools.yaml` shape:\n```yaml\ntools:\n - name: get_post\n description: Get the current post from the open feed page\n script: get_post.ts\n suggestionActions: Open the author profile and review whether the post is worth engaging with\n capabilities:\n readOnlyHint: true\n openWorldHint: false\n inputSchema:\n type: object\n properties:\n pageId:\n type: string\n browserId:\n type: string\n selector:\n type: string\n required:\n - pageId\n```\n\nExample script shape:\n```ts\nexport const run = async ({ page, browser, input, logger }) => {\n const traceContext = logger.getTraceContext();\n logger.info("reading post", { attributes: { selector: input.selector ?? "body", browserId: browser.browserId } });\n const selector = input.selector ?? "body";\n const text = await page.evaluate((currentSelector) => {\n return document.querySelector(currentSelector)?.textContent ?? "";\n }, selector);\n return {\n pageUrl: page.url(),\n traceContext,\n text,\n };\n};\n```\n';const x={name:`custom_script_authoring`,description:`Generate a browse-tool custom tool folder with tools.yaml and TypeScript scripts.`,arguments:[{name:`toolGoal`,description:`What the custom tool should do on the page`,required:!0},{name:`toolName`,description:`Preferred snake_case tool name`,required:!1},{name:`pageContext`,description:`Optional context about the target page or workflow`,required:!1}]},S=new f;function C(e){let t=e.toolName?.trim()||`custom_page_tool`,n=e.pageContext?.trim()||`No extra page context provided.`;return[{role:`user`,content:{type:`text`,text:S.parseAndRenderSync(b,{toolGoal:e.toolGoal,preferredToolName:t,pageContext:n})}}]}export{e as PLAYWRIGHT_TYPES,r as StdioTransportHandler,a as StreamableHttpTransportHandler,_ as ToolExecutionError,g as UnknownToolError,i as container,n as createContainer,y as createServer,x as customScriptAuthoringPrompt,C as generateCustomScriptAuthoringPrompt};
@@ -1,4 +1,4 @@
1
- require(`./streamable-http-u32a2By0.cjs`);let e=require(`node:module`);const t=Symbol.for(`__locatorProxyBrand__`);var n=class e{[t]=!0;constructor(e,t){this.page=e,this.steps=t}getByRole(t,n){return new e(this.page,[...this.steps,{type:`role`,role:t,options:n}])}getByText(t,n){return new e(this.page,[...this.steps,{type:`text`,text:t,options:n}])}getByLabel(t,n){return new e(this.page,[...this.steps,{type:`label`,text:t,options:n}])}getByPlaceholder(t,n){return new e(this.page,[...this.steps,{type:`placeholder`,text:t,options:n}])}getByTestId(t){return new e(this.page,[...this.steps,{type:`testId`,testId:t}])}locator(t){return new e(this.page,[...this.steps,{type:`css`,selector:t}])}filter(t){return new e(this.page,[...this.steps,{type:`filter`,options:t}])}first(){return new e(this.page,[...this.steps,{type:`first`}])}last(){return this.nth(-1)}nth(t){return new e(this.page,[...this.steps,{type:`nth`,index:t}])}async click(e){let t=await this.resolveAndMark(e?.timeout);await this.page.click(t)}async fill(e,t){let n=await this.resolveAndMark(t?.timeout);await this.page.fill(n,e)}async type(e,t){let n=await this.resolveAndMark(t?.timeout);await this.page.type(n,e,{delay:t?.delay})}async press(e){let t=await this.resolveAndMark();await this.page.click(t),await this.page.press(e)}async hover(e){let t=await this.resolveAndMark(e?.timeout);await this.page.hover(t)}async selectOption(e){let t=await this.resolveAndMark();await this.page.selectOption(t,e)}async check(){let e=await this.resolveAndMark();await this.page.click(e)}async uncheck(){let e=await this.resolveAndMark();await this.page.click(e)}async isVisible(){let e=this.buildResolveScript(`isVisible`);return await this.page.evaluate(e)??!1}async isHidden(){return!await this.isVisible()}async isEnabled(){return!await this.evaluateProperty(`disabled`)}async isDisabled(){return!!await this.evaluateProperty(`disabled`)}async isChecked(){return!!await this.evaluateProperty(`checked`)}async evaluateProperty(e){let t=this.buildResolveScript(`getProperty`,e);return this.page.evaluate(t)}async textContent(){let e=this.buildResolveScript(`textContent`);return this.page.evaluate(e)}async innerText(){let e=this.buildResolveScript(`innerText`);return await this.page.evaluate(e)??``}async inputValue(){let e=this.buildResolveScript(`inputValue`);return await this.page.evaluate(e)??``}async count(){let e=this.buildResolveScript(`count`);return await this.page.evaluate(e)??0}async waitFor(e){let t=e?.timeout??5e3,n=e?.state??`visible`,r=Date.now();for(;Date.now()-r<t;){if(n===`visible`&&await this.isVisible()||n===`hidden`&&!await this.isVisible()||n===`attached`&&await this.count()>0||n===`detached`&&await this.count()===0)return;await new Promise(e=>setTimeout(e,100))}throw Error(`Locator waitFor("${n}") timed out after ${t}ms`)}async resolveAndMark(e){let t=e??5e3,n=Date.now(),r=`pw-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;for(;Date.now()-n<t;){let e=this.buildResolveScript(`mark`,r);if(await this.page.evaluate(e))return`[data-pw-proxy="${r}"]`;await new Promise(e=>setTimeout(e,100))}throw Error(`Locator could not resolve element within ${t}ms. Steps: ${this.describeSteps()}`)}describeSteps(){return this.steps.map(e=>{switch(e.type){case`role`:return`getByRole("${e.role}"${e.options?.name?`, { name: "${String(e.options.name)}" }`:``})`;case`text`:return`getByText("${String(e.text)}")`;case`label`:return`getByLabel("${String(e.text)}")`;case`placeholder`:return`getByPlaceholder("${String(e.text)}")`;case`testId`:return`getByTestId("${e.testId}")`;case`css`:return`locator("${e.selector}")`;case`filter`:return`filter(...)`;case`first`:return`first()`;case`nth`:return`nth(${e.index})`}}).join(`.`)}serializeSteps(){return this.steps.map(e=>{if(e.type===`text`||e.type===`label`||e.type===`placeholder`)return{...e,text:e.text instanceof RegExp?{__regex__:e.text.source,flags:e.text.flags}:e.text};if(e.type===`role`&&e.options?.name instanceof RegExp)return{...e,options:{...e.options,name:{__regex__:e.options.name.source,flags:e.options.name.flags}}};if(e.type===`filter`){let t={};return e.options.hasText&&(t.hasText=e.options.hasText instanceof RegExp?{__regex__:e.options.hasText.source,flags:e.options.hasText.flags}:e.options.hasText),e.options.has&&(t.hasSteps=e.options.has.serializeSteps()),{type:`filter`,options:t}}return e})}buildResolveScript(e,t){return`(function() {
1
+ require(`./streamable-http-BLUtoU2x.cjs`);let e=require(`node:module`);const t=Symbol.for(`__locatorProxyBrand__`);var n=class e{[t]=!0;constructor(e,t){this.page=e,this.steps=t}getByRole(t,n){return new e(this.page,[...this.steps,{type:`role`,role:t,options:n}])}getByText(t,n){return new e(this.page,[...this.steps,{type:`text`,text:t,options:n}])}getByLabel(t,n){return new e(this.page,[...this.steps,{type:`label`,text:t,options:n}])}getByPlaceholder(t,n){return new e(this.page,[...this.steps,{type:`placeholder`,text:t,options:n}])}getByTestId(t){return new e(this.page,[...this.steps,{type:`testId`,testId:t}])}locator(t){return new e(this.page,[...this.steps,{type:`css`,selector:t}])}filter(t){return new e(this.page,[...this.steps,{type:`filter`,options:t}])}first(){return new e(this.page,[...this.steps,{type:`first`}])}last(){return this.nth(-1)}nth(t){return new e(this.page,[...this.steps,{type:`nth`,index:t}])}async click(e){let t=await this.resolveAndMark(e?.timeout);await this.page.click(t)}async fill(e,t){let n=await this.resolveAndMark(t?.timeout);await this.page.fill(n,e)}async type(e,t){let n=await this.resolveAndMark(t?.timeout);await this.page.type(n,e,{delay:t?.delay})}async press(e){let t=await this.resolveAndMark();await this.page.click(t),await this.page.press(e)}async hover(e){let t=await this.resolveAndMark(e?.timeout);await this.page.hover(t)}async selectOption(e){let t=await this.resolveAndMark();await this.page.selectOption(t,e)}async check(){let e=await this.resolveAndMark();await this.page.click(e)}async uncheck(){let e=await this.resolveAndMark();await this.page.click(e)}async isVisible(){let e=this.buildResolveScript(`isVisible`);return await this.page.evaluate(e)??!1}async isHidden(){return!await this.isVisible()}async isEnabled(){return!await this.evaluateProperty(`disabled`)}async isDisabled(){return!!await this.evaluateProperty(`disabled`)}async isChecked(){return!!await this.evaluateProperty(`checked`)}async evaluateProperty(e){let t=this.buildResolveScript(`getProperty`,e);return this.page.evaluate(t)}async textContent(){let e=this.buildResolveScript(`textContent`);return this.page.evaluate(e)}async innerText(){let e=this.buildResolveScript(`innerText`);return await this.page.evaluate(e)??``}async inputValue(){let e=this.buildResolveScript(`inputValue`);return await this.page.evaluate(e)??``}async count(){let e=this.buildResolveScript(`count`);return await this.page.evaluate(e)??0}async waitFor(e){let t=e?.timeout??5e3,n=e?.state??`visible`,r=Date.now();for(;Date.now()-r<t;){if(n===`visible`&&await this.isVisible()||n===`hidden`&&!await this.isVisible()||n===`attached`&&await this.count()>0||n===`detached`&&await this.count()===0)return;await new Promise(e=>setTimeout(e,100))}throw Error(`Locator waitFor("${n}") timed out after ${t}ms`)}async resolveAndMark(e){let t=e??5e3,n=Date.now(),r=`pw-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;for(;Date.now()-n<t;){let e=this.buildResolveScript(`mark`,r);if(await this.page.evaluate(e))return`[data-pw-proxy="${r}"]`;await new Promise(e=>setTimeout(e,100))}throw Error(`Locator could not resolve element within ${t}ms. Steps: ${this.describeSteps()}`)}describeSteps(){return this.steps.map(e=>{switch(e.type){case`role`:return`getByRole("${e.role}"${e.options?.name?`, { name: "${String(e.options.name)}" }`:``})`;case`text`:return`getByText("${String(e.text)}")`;case`label`:return`getByLabel("${String(e.text)}")`;case`placeholder`:return`getByPlaceholder("${String(e.text)}")`;case`testId`:return`getByTestId("${e.testId}")`;case`css`:return`locator("${e.selector}")`;case`filter`:return`filter(...)`;case`first`:return`first()`;case`nth`:return`nth(${e.index})`}}).join(`.`)}serializeSteps(){return this.steps.map(e=>{if(e.type===`text`||e.type===`label`||e.type===`placeholder`)return{...e,text:e.text instanceof RegExp?{__regex__:e.text.source,flags:e.text.flags}:e.text};if(e.type===`role`&&e.options?.name instanceof RegExp)return{...e,options:{...e.options,name:{__regex__:e.options.name.source,flags:e.options.name.flags}}};if(e.type===`filter`){let t={};return e.options.hasText&&(t.hasText=e.options.hasText instanceof RegExp?{__regex__:e.options.hasText.source,flags:e.options.hasText.flags}:e.options.hasText),e.options.has&&(t.hasSteps=e.options.has.serializeSteps()),{type:`filter`,options:t}}return e})}buildResolveScript(e,t){return`(function() {
2
2
  var steps = ${JSON.stringify(this.serializeSteps())};
3
3
  var action = "${e}";
4
4
  var extra = ${t===void 0?`null`:JSON.stringify(t)};