import { PageSnapshot, PageReadout, NavigationConfirmRequest, NavigationBridgeAdapter } from '../bridges/navigation.js'; export { PageAction } from '../bridges/navigation.js'; import '../tool-host-BqJRPr_T.js'; import '../types-ITRQFAir.js'; import '../types-D_TzdBsK.js'; /** * The in-page half of DOM co-browsing: a framework-free walker that turns a * live document into a {@link PageSnapshot} of stable handles, and acts on * those handles. * * Extracted from px-ui-sandbox's CoBrowseProvider so a host that does NOT own * the page (Genie's browser, showing sites through an Electron * WebContentsView) can run the same walker, injected into an isolated world. * * Constraints this file holds, because the injected IIFE is built from it: * * - NO runtime imports. Type-only imports are erased; anything else would be * bundled into a script that must run with no module loader. * - Nothing touches `document` / `window` until a method is called, so the * script can be evaluated in a context with no DOM at all. * - Every result is plain, structured-cloneable data. * * Trust boundary: the page is hostile input. It controls every attribute, * label and text node read here. Two consequences: * - Sensitive values (passwords, card fields, one-time codes, anything marked * `data-private`) are masked HERE, before anything leaves the page — the host * cannot mask what it has already received. * - Handles are compared as plain strings, never spliced into a CSS selector, * so a crafted handle cannot change what a lookup matches. */ /** Elements the walker considers actionable. */ declare const INTERACTIVE = "a[href], button, input, select, textarea, [role=button], [role=link], [role=checkbox], [role=tab], [data-co-handle]"; /** Every method the in-page agent answers. The wire protocol is exactly this list. */ declare const DOM_NAVIGATION_METHODS: readonly ["getLocation", "describe", "read", "visit", "back", "forward", "scrollTo", "scrollBy", "setField", "click", "submit", "rectFor"]; type DomNavigationMethod = (typeof DOM_NAVIGATION_METHODS)[number]; type ActionResult = { ok: boolean; error?: string; }; type HandleRect = { x: number; y: number; width: number; height: number; }; type FieldElement = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement; declare function isVisible(el: Element): boolean; /** Sensitive fields whose value is never read into the snapshot. */ declare function isSensitive(el: Element): boolean; declare function roleOf(el: Element): string; declare function accessibleName(el: Element): string; declare function isDestructive(el: Element, label: string): boolean; /** * The element's own stable handle: data-co-handle → name → id, or "" when it * has none. An EMPTY attribute counts as absent — `button.name` is `""`, not * null, on every button, anchor and input without one, so a plain `??` chain * never reaches the id. */ declare function attributeHandle(el: Element): string; /** * Build a fresh snapshot + a handle→element registry. Handle preference: * data-co-handle → name → id → `role#index` (stable within a snapshot). */ declare function walk(doc?: Document): { snapshot: PageSnapshot; registry: Map; }; /** * Set a field's value so a React-controlled input sees the change. * * - Text, textarea, select: call the PROTOTYPE `value` setter (React shadows * `value` on the instance with its value tracker), then dispatch bubbling * `input` + `change`. * - Checkbox, radio: React's onChange for these listens to `click`, not * `input` / `change`, so the write is a real `click()` — the browser toggles * the box and fires click, input and change itself. Only when the state * actually differs, so setting the current value is a no-op rather than a * toggle. A radio cannot be unchecked by clicking it; that one case falls * back to the setter. */ declare function setNativeValue(el: FieldElement, value: unknown): void; /** * Visible text / heading outline, with sensitive text removed. Structured, so * the bridge can render each page-supplied string on its own single line. */ declare function readPage(doc?: Document): PageReadout; type DomNavigationAgentOptions = { /** Document to drive. Default: the global `document`, read lazily. */ document?: Document; /** * Called just before the agent acts on the page — before resolving a field * for `setField`, and after resolving (only when the element exists) for * `click` / `submit`. The sandbox uses it to attribute the request an action * causes to the agent. */ beforeAction?: (action: "setField" | "click" | "submit") => void; }; type DomNavigationAgent = { getLocation(): { url: string; title: string; }; describe(): PageSnapshot; read(): PageReadout; /** Navigate. Only http(s) or same-site paths; deferred a tick so a remote call returns first. */ visit(url: string): void; back(): void; forward(): void; scrollTo(opts: { x?: number; y?: number; handle?: string; }): void; scrollBy(dy: number): void; setField(handle: string, value: unknown): ActionResult; click(handle: string): ActionResult; submit(handle: string): ActionResult; rectFor(handle: string): HandleRect | null; /** Element for a handle: this snapshot's registry, then a live attribute lookup. */ resolve(handle: string): Element | null; /** Serialisable dispatch — what the injected script exposes to a host. */ call(method: DomNavigationMethod, args?: unknown[]): unknown; }; declare function createDomNavigationAgent(options?: DomNavigationAgentOptions): DomNavigationAgent; /** * The host half: a {@link NavigationBridgeAdapter} that drives a page it does * not run in, through any transport that can carry a method name and plain * arguments into the page and a plain result back — Electron's * `executeJavaScript` / `executeJavaScriptInIsolatedWorld`, a MessagePort, a * WebSocket to a remote browser. * * Every result is treated as hostile: the page owns the DOM the in-page walker * reads, and if the script was injected into the MAIN world the page can * replace the walker outright. So results are coerced to the declared shapes * here, and anything malformed is dropped rather than passed on to the agent. */ /** The global the injected script installs in the world it runs in. */ declare const DOM_NAVIGATION_GLOBAL = "__fancyDomNavigation"; /** Bumped only if the wire protocol changes incompatibly. */ declare const DOM_NAVIGATION_PROTOCOL = 1; /** * Carries one call into the page. `args` and the resolved value are plain, * structured-cloneable data. Reject (or throw) when the call could not be * delivered — e.g. the page navigated and the script must be re-injected. */ type DomNavigationTransport = { call(method: DomNavigationMethod, args: unknown[]): Promise; }; type RemoteNavigationAdapterOptions = { transport: DomNavigationTransport; /** Optional fancy-screens screen id for presence targeting. */ screenId?: string; /** Human-control revision, if the host tracks one. Omit to disable stale-intent protection. */ getRevision?: () => number | Promise; /** * Trust-but-verify. Without it, `page_submit` and destructive `page_click` * are NOT staged — they run as soon as the agent asks. A host showing pages * it does not own should always supply one. */ confirm?: (req: NavigationConfirmRequest) => Promise; }; /** * A JavaScript expression that performs one call against the injected global — * what a host passes to `executeJavaScript`. Arguments are embedded as JSON, * which is a valid JS expression, so no argument can break out of its literal. */ declare function domNavigationCallScript(method: DomNavigationMethod, args?: unknown[]): string; /** Build a NavigationBridgeAdapter backed by a transport into the page. */ declare function createRemoteNavigationAdapter(options: RemoteNavigationAdapterOptions): NavigationBridgeAdapter; export { type ActionResult, DOM_NAVIGATION_GLOBAL, DOM_NAVIGATION_METHODS, DOM_NAVIGATION_PROTOCOL, type DomNavigationAgent, type DomNavigationAgentOptions, type DomNavigationMethod, type DomNavigationTransport, type HandleRect, INTERACTIVE, NavigationBridgeAdapter, NavigationConfirmRequest, PageReadout, PageSnapshot, type RemoteNavigationAdapterOptions, accessibleName, attributeHandle, createDomNavigationAgent, createRemoteNavigationAdapter, domNavigationCallScript, isDestructive, isSensitive, isVisible, readPage, roleOf, setNativeValue, walk };