{"version":3,"sources":["dom-navigation-inject:virtual:dom-navigation-inject","../src/dom-navigation/script.ts"],"names":[],"mappings":";;;AAAA,IAAA,qCAAA,GAAA,gxWAAA;;;ACcO,IAAM,qBAAA,GAAgC","file":"dom-navigation-script.cjs","sourcesContent":["\"use strict\";\n(() => {\n  // src/dom-navigation/agent.ts\n  var INTERACTIVE = \"a[href], button, input, select, textarea, [role=button], [role=link], [role=checkbox], [role=tab], [data-co-handle]\";\n  var tag = (el) => el.tagName.toUpperCase();\n  function isVisible(el) {\n    const he = el;\n    if (el.type === \"hidden\") return false;\n    if (he.hidden || he.getAttribute(\"aria-hidden\") === \"true\") return false;\n    return he.offsetParent !== null || he.getClientRects().length > 0;\n  }\n  function isSensitive(el) {\n    const input = el;\n    const ac = (el.getAttribute(\"autocomplete\") ?? \"\").toLowerCase();\n    return input.type === \"password\" || ac.startsWith(\"cc-\") || ac === \"one-time-code\" || el.hasAttribute(\"data-private\");\n  }\n  function insideSensitive(node) {\n    for (let el = node.parentElement; el; el = el.parentElement) {\n      if (isSensitive(el)) return true;\n    }\n    return false;\n  }\n  function safeText(root) {\n    const doc = root.ownerDocument ?? root;\n    const walker = doc.createTreeWalker(root, 4);\n    let out = \"\";\n    for (let n = walker.nextNode(); n; n = walker.nextNode()) {\n      if (!insideSensitive(n)) out += n.nodeValue ?? \"\";\n    }\n    return out;\n  }\n  function roleOf(el) {\n    const explicit = el.getAttribute(\"role\");\n    if (explicit) return explicit;\n    const t = tag(el);\n    if (t === \"A\") return \"link\";\n    if (t === \"BUTTON\") return \"button\";\n    if (t === \"SELECT\") return \"select\";\n    if (t === \"TEXTAREA\") return \"textbox\";\n    if (t === \"INPUT\") {\n      const type = el.type;\n      if (type === \"checkbox\") return \"checkbox\";\n      if (type === \"radio\") return \"radio\";\n      if (type === \"submit\" || type === \"button\") return \"button\";\n      return \"textbox\";\n    }\n    return \"generic\";\n  }\n  function labelFor(doc, id) {\n    for (const lbl of Array.from(doc.querySelectorAll(\"label[for]\"))) {\n      if (lbl.getAttribute(\"for\") === id) return lbl;\n    }\n    return null;\n  }\n  function accessibleName(el) {\n    const doc = el.ownerDocument;\n    const aria = el.getAttribute(\"aria-label\");\n    if (aria) return aria.trim();\n    const labelledby = el.getAttribute(\"aria-labelledby\");\n    if (labelledby) {\n      const txt = labelledby.split(/\\s+/).map((id2) => doc.getElementById(id2)?.textContent ?? \"\").join(\" \").trim();\n      if (txt) return txt;\n    }\n    const id = el.getAttribute(\"id\");\n    if (id) {\n      const lbl = labelFor(doc, id);\n      if (lbl?.textContent?.trim()) return lbl.textContent.trim();\n    }\n    const wrapping = el.closest(\"label\");\n    if (wrapping) {\n      const txt = safeText(wrapping).trim();\n      if (txt) return txt;\n    }\n    const placeholder = el.getAttribute(\"placeholder\");\n    if (placeholder) return placeholder.trim();\n    const text = isSensitive(el) ? \"\" : el.textContent?.trim();\n    if (text) return text.replace(/\\s+/g, \" \").slice(0, 80);\n    return el.getAttribute(\"name\") ?? el.getAttribute(\"id\") ?? roleOf(el);\n  }\n  function isDestructive(el, label) {\n    if (el.hasAttribute(\"data-co-confirm\")) return true;\n    if (el.type === \"submit\") return true;\n    if (tag(el) === \"BUTTON\" && el.type === \"submit\") return true;\n    return /\\b(delete|remove|destroy|sign out|log ?out|cancel subscription|deactivate)\\b/i.test(label);\n  }\n  function attributeHandle(el) {\n    return el.getAttribute(\"data-co-handle\") || el.getAttribute(\"name\") || el.getAttribute(\"id\") || \"\";\n  }\n  function walk(doc = document) {\n    const registry = /* @__PURE__ */ new Map();\n    const actions = [];\n    const seen = /* @__PURE__ */ new Set();\n    let synthetic = 0;\n    for (const el of Array.from(doc.querySelectorAll(INTERACTIVE))) {\n      if (seen.has(el) || !isVisible(el)) continue;\n      seen.add(el);\n      const label = accessibleName(el);\n      const role = roleOf(el);\n      let handle = attributeHandle(el);\n      if (!handle || registry.has(handle)) handle = `${role}#${synthetic++}`;\n      registry.set(handle, el);\n      let value;\n      if (role === \"textbox\" || role === \"select\") {\n        value = isSensitive(el) ? void 0 : el.value;\n      } else if (role === \"checkbox\" || role === \"radio\") {\n        value = el.checked;\n      }\n      const action = { handle, role, label, destructive: isDestructive(el, label) };\n      if (value !== void 0) action.value = value;\n      actions.push(action);\n    }\n    const loc = doc.defaultView?.location;\n    return {\n      snapshot: { url: loc ? loc.pathname + loc.search : \"\", title: doc.title, actions },\n      registry\n    };\n  }\n  function isField(el) {\n    const t = tag(el);\n    return t === \"INPUT\" || t === \"TEXTAREA\" || t === \"SELECT\";\n  }\n  function setNativeValue(el, value) {\n    const view = el.ownerDocument.defaultView ?? globalThis;\n    const fire = () => {\n      el.dispatchEvent(new view.Event(\"input\", { bubbles: true }));\n      el.dispatchEvent(new view.Event(\"change\", { bubbles: true }));\n    };\n    const t = tag(el);\n    if (t === \"INPUT\" && (el.type === \"checkbox\" || el.type === \"radio\")) {\n      const input = el;\n      const want = Boolean(value);\n      if (input.checked === want) return;\n      if (input.type === \"checkbox\" || want) {\n        input.click();\n        return;\n      }\n      const setter2 = Object.getOwnPropertyDescriptor(view.HTMLInputElement.prototype, \"checked\")?.set;\n      setter2?.call(el, false);\n      fire();\n      return;\n    }\n    const proto = t === \"TEXTAREA\" ? view.HTMLTextAreaElement.prototype : t === \"SELECT\" ? view.HTMLSelectElement.prototype : view.HTMLInputElement.prototype;\n    const setter = Object.getOwnPropertyDescriptor(proto, \"value\")?.set;\n    setter?.call(el, String(value));\n    fire();\n  }\n  function readPage(doc = document) {\n    const main = doc.querySelector(\"main\") ?? doc.body;\n    if (!main) return { title: doc.title, headings: [], text: \"\" };\n    const headings = Array.from(main.querySelectorAll(\"h1, h2, h3\")).map((h) => ({\n      level: Number(h.tagName.slice(1)),\n      text: safeText(h).trim()\n    }));\n    const text = safeText(main).replace(/\\s+/g, \" \").trim().slice(0, 4e3);\n    return { title: doc.title, headings, text };\n  }\n  function findByAttribute(doc, attr, value) {\n    for (const el of Array.from(doc.querySelectorAll(`[${attr}]`))) {\n      if (el.getAttribute(attr) === value) return el;\n    }\n    return null;\n  }\n  var num = (v) => typeof v === \"number\" ? v : void 0;\n  function createDomNavigationAgent(options = {}) {\n    let registry = /* @__PURE__ */ new Map();\n    const doc = () => options.document ?? document;\n    const win = () => doc().defaultView ?? window;\n    const before = (action) => options.beforeAction?.(action);\n    const resolve = (handle) => {\n      const hit = registry.get(handle);\n      if (hit && hit.isConnected) return hit;\n      const d = doc();\n      return findByAttribute(d, \"data-co-handle\", handle) ?? findByAttribute(d, \"name\", handle) ?? d.getElementById(handle);\n    };\n    const agent = {\n      getLocation: () => {\n        const loc = win().location;\n        return { url: loc.pathname + loc.search, title: doc().title };\n      },\n      describe: () => {\n        const res = walk(doc());\n        registry = res.registry;\n        return res.snapshot;\n      },\n      read: () => readPage(doc()),\n      visit: (url) => {\n        const w = win();\n        const target = new URL(String(url), w.location.href);\n        if (target.protocol !== \"http:\" && target.protocol !== \"https:\") {\n          throw new Error(`Refusing to navigate to a '${target.protocol}' URL.`);\n        }\n        w.setTimeout(() => w.location.assign(target.href), 0);\n      },\n      back: () => win().history.back(),\n      forward: () => win().history.forward(),\n      scrollTo: ({ x, y, handle }) => {\n        const w = win();\n        if (handle) {\n          resolve(handle)?.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n          return;\n        }\n        w.scrollTo({ left: x ?? w.scrollX, top: y ?? w.scrollY, behavior: \"smooth\" });\n      },\n      scrollBy: (dy) => win().scrollBy({ top: dy, behavior: \"smooth\" }),\n      setField: (handle, value) => {\n        before(\"setField\");\n        const el = resolve(handle);\n        if (!el) return { ok: false, error: `No element for handle \"${handle}\"` };\n        if (isField(el)) {\n          setNativeValue(el, value);\n          return { ok: true };\n        }\n        return { ok: false, error: `Handle \"${handle}\" is not a form field` };\n      },\n      click: (handle) => {\n        const el = resolve(handle);\n        if (!el) return { ok: false, error: `No element for handle \"${handle}\"` };\n        before(\"click\");\n        el.click();\n        return { ok: true };\n      },\n      submit: (handle) => {\n        const el = resolve(handle);\n        if (!el) return { ok: false, error: `No element for handle \"${handle}\"` };\n        const form = tag(el) === \"FORM\" ? el : el.closest(\"form\");\n        if (!form) return { ok: false, error: `Handle \"${handle}\" is not inside a form` };\n        before(\"submit\");\n        if (typeof form.requestSubmit === \"function\") form.requestSubmit();\n        else form.submit();\n        return { ok: true };\n      },\n      rectFor: (handle) => {\n        const el = resolve(handle);\n        if (!el) return null;\n        const r = el.getBoundingClientRect();\n        return { x: r.left, y: r.top, width: r.width, height: r.height };\n      },\n      resolve,\n      call: (method, args = []) => {\n        const a = Array.isArray(args) ? args : [];\n        const handle = String(a[0] ?? \"\");\n        switch (method) {\n          case \"getLocation\":\n            return agent.getLocation();\n          case \"describe\":\n            return agent.describe();\n          case \"read\":\n            return agent.read();\n          case \"visit\":\n            agent.visit(String(a[0] ?? \"\"));\n            return void 0;\n          case \"back\":\n            agent.back();\n            return void 0;\n          case \"forward\":\n            agent.forward();\n            return void 0;\n          case \"scrollTo\": {\n            const o = a[0] && typeof a[0] === \"object\" ? a[0] : {};\n            agent.scrollTo({\n              x: num(o.x),\n              y: num(o.y),\n              handle: typeof o.handle === \"string\" ? o.handle : void 0\n            });\n            return void 0;\n          }\n          case \"scrollBy\":\n            agent.scrollBy(Number(a[0] ?? 0));\n            return void 0;\n          case \"setField\":\n            return agent.setField(handle, a[1]);\n          case \"click\":\n            return agent.click(handle);\n          case \"submit\":\n            return agent.submit(handle);\n          case \"rectFor\":\n            return agent.rectFor(handle);\n          default:\n            throw new Error(`Unknown dom-navigation method: ${String(method)}`);\n        }\n      }\n    };\n    return agent;\n  }\n\n  // src/dom-navigation/inject.ts\n  var KEY = \"__fancyDomNavigation\";\n  var PROTOCOL = 1;\n  var g = globalThis;\n  var existing = g[KEY];\n  if (!existing || existing.protocol !== PROTOCOL) {\n    const agent = createDomNavigationAgent();\n    Object.defineProperty(globalThis, KEY, {\n      configurable: true,\n      enumerable: false,\n      writable: false,\n      value: Object.freeze({\n        protocol: PROTOCOL,\n        call: (method, args) => agent.call(method, args)\n      })\n    });\n  }\n})();\n","/**\n * `@particle-academy/agent-integrations/dom-navigation/script`\n *\n * The in-page walker as one self-contained script string — no imports, no\n * module system — for a host to inject into a page it does not own:\n *\n *   await webContents.executeJavaScriptInIsolatedWorld(worldId, [{ code: DOM_NAVIGATION_SCRIPT }]);\n *\n * Built at package build time from ./inject.ts (see\n * scripts/dom-navigation-inject-plugin.ts). Its own subpath so a host process\n * that only injects never loads the walker as a module, and vice versa.\n */\nimport source from \"virtual:dom-navigation-inject\";\n\nexport const DOM_NAVIGATION_SCRIPT: string = source;\n"]}