Stabilize recording/replay with robust iframe handling, noise suppression, and deterministic clicks #87
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Records iframe interactions reliably without flooding steps.
Replays deterministic steps inside the correct iframe instead of navigating into the iframe URL.
Filters ad/analytics/recaptcha iframe navigations and about:blank.
Deduplicates steps (including scroll/input/click) to match real user intent.
Extension: Content (src/entrypoints/content.ts)
Enabled all frames and about:blank: allFrames: true, matchAboutBlank: true.
Added frame context on all events: frameUrl, frameIdPath, isTopFrame.
Input noise reduction: isTrusted checks, debounce per element, skip rapid empty repeats.
New-tab intent signal: PREPARE_NEW_TAB emitted on modifier/middle-clicks and target=_blank.
Extension: Background (src/entrypoints/background.ts)
Activated tab gating + new-tab intent correlation; ignore unactivated/background tabs.
Iframe nav filtering:
Tracks interactedFrameUrls per tab; only accepts rrweb Meta navigations from frames the user interacted with.
Drops about:blank; adds time-window gating (defaults to 3s after interaction).
Allow/deny logic (allowlist overrides blocklist), with settings persisted.
rrweb payload handling:
Scroll: merge consecutive updates; suppress chrome://newtab; dedupe identical XY within 200ms regardless of targetId.
Meta: convert to navigation step only if allowed by the above rules.
Step dedupe post-pass: collapse consecutive duplicates for navigation/input/click/scroll/key_press; update timestamp/screenshot instead of appending.
Navigation consolidation: per-tab merge of redirects to reduce churn.
Persisted recording state: default stopped; load/broadcast on startup; save on start/stop.
Extension: Types/Schema
types.ts: Added optional frameIdPath to StoredCustom* and frameUrl to rrweb.
workflow-types.ts: Promoted frameIdPath to Step types (Click/Input/KeyPress/Navigation/Scroll).
Backend (workflows/workflow_use)
Recorder safety filter (recorder/service.py): drop about:blank and obvious ad/analytics hosts before saving workflow.
Controller models (controller/views.py): RecorderBase now includes url and frameIdPath so steps carry frame/page hints.
Deterministic controller (controller/service.py):
Clicks execute inside the correct iframe:
Resolve context by frameIdPath (preferred) or frameUrl (origin+prefix).
Do not navigate to iframe URLs; only auto-navigate for top-document clicks without frame hints.
Fallback: search all frames (prioritize target origin) to find selector.
Increased click timeout to 2500ms.
Workflow runner (workflow/service.py):
Skip “pre-wait for next selector” when next step’s declared url/frameUrl differs from current page URL to avoid false failures between pages.
Noise/Correctness
Prevent duplicate steps due to pointer-only variance and consecutive identical content.
Drop spurious iframe navigations (recaptcha/ads/metrics).
State is consistent across reloads; recording does not auto-start unexpectedly.
Additional Notes
Frame resolution uses frameIdPath first; frameUrl fallback matches origin + prefix to disambiguate.