/** * Screen-change detection primitives for the browser auto-answer loop. * * The loop has to notice that the question/page changed *while a vision call is * in flight* (those calls run 50-120s), otherwise a stale answer is applied to * the next screen. The in-page MutationObserver is one of the two signals that * feed that decision - and it is document-scoped, so it must be RE-INJECTED * after every (main-frame) navigation, otherwise the heartbeat's DOM path is * dead for the rest of the run. * * Everything here is pure (no I/O) so it can be unit-tested, and the injected * observer script is built from the SAME `observerChangeScore` source so the * tested code is literally the code that runs in the page. */ /** Score threshold above which the observer reports a material change. */ export declare const SCREEN_CHANGE_THRESHOLD = 15; /** * In-page observer scoring: compares the serialized element texts the * MutationObserver watches (`getText()` output) and returns a weighted score. * Kept dependency-free so it can be serialized into the injected script via * `toString()`. * * Weights (mirror the Node-side fingerprint): an added or removed element is * 10, a shifted/replaced one is 8. A full question swap clears the threshold. */ export declare function observerChangeScore(prevText: string, currText: string): number; /** * True only for a MAIN-frame navigation. Subframe/iframe navigations (ads, * embedded widgets) must not flag the bound page as changed or trigger a * re-inject into an unrelated document. */ export declare function isMainFrameNavigation(params: { frame?: { parentId?: string; }; } | null | undefined): boolean; /** * Build the injected MutationObserver script. `observerChangeScore` is embedded * from its own source so the unit-tested function is the one that runs in-page. * The script is idempotent: it early-returns when its Symbol key already exists * on the current document. */ export declare function buildObserverScript(): string;