You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/chrome/ARCHITECTURE.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -420,7 +420,7 @@ System prompt has a new "MODALS & DIALOGS" section that describes the intended f
420
420
421
421
### Duplicate-submit guard (v3.6.5+)
422
422
423
-
Before any `click` whose resolved text matches `^(create|save|submit|add|post|publish|send|confirm|place order|pay|checkout|update|finish|done)\b` the agent checks a per-tab+URL 45-second window. Duplicate clicks in that window are blocked unless `_allowResubmit` is set. Prevents the "clicked Create three times → three products created" failure mode.
423
+
Before any submit-like text `click`, the agent checks a per-tab+URL 45-second window. Duplicate clicks in that window are blocked unless `_allowResubmit` is set; an acknowledged retry re-arms the window, so a further rapid duplicate needs its own acknowledgement. The browser-free guard is byte-identical in Chrome and Firefox, preventing the "clicked Create three times → three products created" failure mode in both builds.
const fresh = buf.filter(e => now - e.ts < 45000);
15846
-
const match = fresh.find(e => e.key === key);
15847
-
if (match) {
15848
-
return {
15849
-
success: false,
15850
-
dispatched: false,
15851
-
blockedDuplicateSubmit: true,
15852
-
error: `Blocked: you already clicked "${rawText}" on this page ${Math.round((now - match.ts) / 1000)}s ago and the URL has not changed since. Stripe-style UIs often reuse the same label for the modal-OPEN button and the SUBMIT button inside the modal — a second click typically creates a duplicate record. Before clicking "${rawText}" again, verify: (a) that all required fields are actually filled by reading the form/page, (b) that this click is intended as a FIRST submit and not a retry. If the previous click did nothing because a field was empty, fill the field first. If you genuinely need to retry, pass _allowResubmit: true in the args.`,
error: `Blocked: you already clicked "${rawText}" on this page ${Math.round((timestamp-match.ts)/1000)}s ago and the URL has not changed since. Stripe-style UIs often reuse the same label for the modal-OPEN button and the SUBMIT button inside the modal — a second click typically creates a duplicate record. Before clicking "${rawText}" again, verify: (a) that all required fields are actually filled by reading the form/page, (b) that this click is intended as a FIRST submit and not a retry. If the previous click did nothing because a field was empty, fill the field first. If you genuinely need to retry, pass _allowResubmit: true in the args.`,
-**No shadow DOM piercing** — content script can read open shadow roots via `element.shadowRoot`, but cannot pierce closed roots.
12
12
-**No offscreen document** — no HTTP fetch proxy for localhost LLM servers with Private Network Access / CORS issues. User must ensure their local LLM server sends permissive CORS headers.
13
-
-**No duplicate-submit guard** — the per-tab submit-throttle (Chrome v3.6.5+) is still Chrome-only. Firefox's agent loop does not block rapid duplicate Create/Submit clicks. `blockedDone` and the ambiguous-click candidate payload were ported to Firefox in v4.0.1 (see "Overlay defenses" below).
Everything else — the agent loop, LLM providers, site adapters, Ask/Act/Dev mode routing, Plan before Act, loop detection, API shortcut observer, trace recorder, scheduler, context management — is architecturally identical to Chrome unless noted below.
@@ -173,10 +172,9 @@ Firefox's AX tools use synthetic events only — there is no trusted-event path.
173
172
174
173
### What was intentionally skipped in the Firefox port
175
174
176
-
These Chrome v3.6.x features depend on CDP or agent-level state and were not ported — they can be re-evaluated later:
175
+
These Chrome v3.6.x features depend on CDP and were not ported — they can be re-evaluated later:
177
176
178
177
-**CDP-enriched `click_ax` frontmost resolution** — when `click_ax` lands on a node that overlaps many candidates, Chrome re-queries via CDP to pick the frontmost hit. Firefox relies on the initial ref_id resolution plus the v4.0.1 occlusion hit-test (see below).
179
-
-**Duplicate-submit guard** — Chrome's agent.js tracks recent submit tool calls and blocks duplicates within a short window. Not in Firefox's agent loop.
180
178
-**Offscreen fetch fallback** — Chrome falls through to an offscreen-document proxy when direct fetch fails (common for localhost LLM servers and private-network destinations). Firefox has no offscreen API; local servers must handle CORS themselves.
181
179
182
180
### Overlay defenses (v4.0.1+)
@@ -191,6 +189,16 @@ Brought to Chrome parity in v4.0.1 — same three layers, synthetic-event-safe s
191
189
192
190
System prompt has a new "MODALS & DIALOGS" section describing the intended flow and the "dialog still open" failure pattern.
193
191
192
+
### Duplicate-submit guard
193
+
194
+
Submit-like text clicks use the same browser-free guard as Chrome. The first
195
+
click is recorded by tab, normalized label, and current URL; another matching
196
+
click within 45 seconds is blocked unless `_allowResubmit` explicitly
197
+
acknowledges the retry. An acknowledged retry re-arms the window, so a further
198
+
rapid duplicate needs its own acknowledgement. Navigation, expired entries,
199
+
ordinary labels, and validation-rejected submits remain eligible for a fresh
200
+
click.
201
+
194
202
---
195
203
196
204
## Skills and Dynamic Skill Tools
@@ -547,7 +555,6 @@ when the tab conversation already has `/allow-api`.
547
555
| No full-page screenshot | Only visible viewport | Scroll + multiple captures |
548
556
| No shadow-root piercing (closed) | Can't read closed shadow roots | Dev-mode `execute_js` with manual traversal |
549
557
| No arbitrary-path/CDP upload | Cannot attach an arbitrary local path silently | Use a prior `downloadId` re-fetch or WebBrain's user file picker |
550
-
| No duplicate-submit guard | Agent may submit twice if LLM loops | Rely on site-level idempotence / user watches |
551
558
| No ambiguous-click CDP enrichment | Overlapping hit-target ambiguity resolved by ref_id only | Prompting / adapter guidance |
552
559
| MV2 background page | Less efficient than MV3 service worker |`persistent: false` helps |
error: `Blocked: you already clicked "${rawText}" on this page ${Math.round((timestamp-match.ts)/1000)}s ago and the URL has not changed since. Stripe-style UIs often reuse the same label for the modal-OPEN button and the SUBMIT button inside the modal — a second click typically creates a duplicate record. Before clicking "${rawText}" again, verify: (a) that all required fields are actually filled by reading the form/page, (b) that this click is intended as a FIRST submit and not a retry. If the previous click did nothing because a field was empty, fill the field first. If you genuinely need to retry, pass _allowResubmit: true in the args.`,
0 commit comments