/** * Weavetab — cdp/ref_cache.ts * Unified Ref Coordinate Cache (URC) * * Single in-memory, per-tab store of refId → {selector, x, y, backendNodeId, fingerprint} * populated once by buildActionMap/buildAXTreeMap and read by every interaction tool. * * Design goals: * - Zero extra CDP calls on cache hit (< TTL) * - One atomic Runtime.evaluate on stale/miss (atomicResolve) * - Keyed strictly by targetId (frame-scoped) — iframe contexts never bleed * - Auto-invalidated on frameNavigated * * Weavetab by fy2ne */ import CDP from "chrome-remote-interface"; export interface RefCoordEntry { /** Primary selector — [data-wt-id="..."] form preferred */ selector: string; /** Center X at capture time */ x: number; /** Center Y at capture time */ y: number; /** Epoch ms — for TTL gate */ capturedAt: number; /** CDP backendNodeId for re-resolution via DOM.getBoxModel when selector fails */ backendNodeId?: number; /** * Lightweight identity string: "tag:role:labelPrefix" * Checked inside atomicResolve to detect DOM replacement (re-render). */ fingerprint: string; /** Holographic: visual bounding box hash for deduplication */ visualHash?: string; /** Holographic: full or partial XPath */ xpath?: string; /** Holographic: current value for stateful tracking */ value?: string; /** Holographic: label text */ label?: string; } export interface AtomicResolveResult { status: "OK" | "NOT_FOUND" | "STALE" | "INVISIBLE" | "SHADOW"; x?: number; y?: number; } /** Default TTL: 30 seconds. Overridden by config.refCacheTtlMs at call sites. */ export declare const DEFAULT_URC_TTL_MS = 30000; /** Returns stale miss rate [0–1] for the last observation window. */ export declare function getStaleMissRate(hostname: string): number; /** Write an entry into the URC for a given tab and refId. */ export declare function urcSet(targetId: string, refId: string, entry: RefCoordEntry): void; /** * Read an entry from the URC. * Returns null if: not found, OR entry is older than maxAgeMs. */ export declare function urcGet(targetId: string, refId: string, maxAgeMs?: number): RefCoordEntry | null; /** Return all cached entries for a tab (used by health checks and delta validation). */ export declare function urcGetAll(targetId: string): Map; /** * Invalidate all URC entries for a tab. * Must be called on: frameNavigated, full map rebuild, tab close. */ export declare function urcInvalidate(targetId: string): void; /** * Bulk-populate the URC from a freshly built ActionElement array. * Called at the end of buildActionMap and buildAXTreeMap. * Only writes entries that have both x and selector defined. */ export declare function urcPopulate(targetId: string, elements: Array<{ id: string; selector?: string; x?: number; y?: number; backendNodeId?: number; role?: string; label?: string; value?: string; type?: string; fingerprint?: string; visualHash?: string; xpath?: string; }>): void; /** * Single CDP Runtime.evaluate that simultaneously: * 1. Finds the element via selector (with WeakMap re-hydration fallback) * 2. Validates tag/role fingerprint (lightweight string check) * 3. Returns fresh coordinates from getBoundingClientRect * * Cost: 1 CDP call (~2–5ms). On a URC cache hit this is the ONLY extra call made. * On a full miss (Stage 3+) it is still cheaper than re-running buildActionMap. */ export declare function atomicResolve(session: CDP.Client, selector: string, fingerprint?: string, hostname?: string): Promise; /** * Attempt coordinate resolution via CDP DOM.getBoxModel using a backendNodeId. * Used as Stage 4 in the click fallback chain when the selector path is unavailable. */ export declare function resolveViaBackendNodeId(session: CDP.Client, backendNodeId: number): Promise<{ x: number; y: number; } | null>;