@enricai/barnacle 1.9.11 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/scraper/browser-click-expr.d.ts +44 -0
  2. package/dist/scraper/browser-click-expr.d.ts.map +1 -0
  3. package/dist/scraper/browser-click-expr.js +69 -0
  4. package/dist/scraper/browser-click-expr.js.map +1 -0
  5. package/dist/scraper/deep-locator-candidates.d.ts +85 -23
  6. package/dist/scraper/deep-locator-candidates.d.ts.map +1 -1
  7. package/dist/scraper/deep-locator-candidates.js +120 -40
  8. package/dist/scraper/deep-locator-candidates.js.map +1 -1
  9. package/dist/scraper/deep-locator-click.d.ts +40 -2
  10. package/dist/scraper/deep-locator-click.d.ts.map +1 -1
  11. package/dist/scraper/deep-locator-click.js +29 -3
  12. package/dist/scraper/deep-locator-click.js.map +1 -1
  13. package/dist/scraper/deep-locator-fake.d.ts.map +1 -1
  14. package/dist/scraper/deep-locator-fake.js +1 -0
  15. package/dist/scraper/deep-locator-fake.js.map +1 -1
  16. package/dist/scraper/deep-locator-scan.d.ts +30 -16
  17. package/dist/scraper/deep-locator-scan.d.ts.map +1 -1
  18. package/dist/scraper/deep-locator-scan.js +65 -25
  19. package/dist/scraper/deep-locator-scan.js.map +1 -1
  20. package/dist/scraper/deep-query.d.ts +5 -5
  21. package/dist/scraper/deep-query.d.ts.map +1 -1
  22. package/dist/scraper/deep-query.js +7 -9
  23. package/dist/scraper/deep-query.js.map +1 -1
  24. package/dist/scraper/flow-runner.d.ts +7 -7
  25. package/dist/scraper/flow-runner.d.ts.map +1 -1
  26. package/dist/scraper/flow-runner.js +190 -96
  27. package/dist/scraper/flow-runner.js.map +1 -1
  28. package/dist/scraper/submit-control.d.ts +5 -3
  29. package/dist/scraper/submit-control.d.ts.map +1 -1
  30. package/dist/scraper/submit-control.js +7 -7
  31. package/dist/scraper/submit-control.js.map +1 -1
  32. package/package.json +1 -1
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Shared browser-context click-activation snippet. Three primitives —
3
+ * `buildClickFrameCandidateExpr` (`deep-locator-scan.ts`),
4
+ * `buildDeepSubmitClickExpr` (`deep-query.ts`), and `buildClickByDeepIndexExpr`
5
+ * (`submit-control.ts`) — each need to activate a resolved element from inside
6
+ * a `page.evaluate`/`Frame.evaluate` string. They used to dispatch bare
7
+ * `new Event("mousedown"/"mouseup"/"click", { bubbles: true })`, which BUBBLES
8
+ * (so analytics/telemetry listeners fire) but is NOT a `MouseEvent`/`PointerEvent`
9
+ * instance — React's synthetic-event system and design-system widgets (Base Web,
10
+ * etc.) refuse a bare `Event` as a real user activation. The observed symptom on
11
+ * a markerless multi-select wizard: an option/toggle click reached the element
12
+ * and its analytics pixel recorded the click, yet the widget's "N selected"
13
+ * counter stayed flat because the selection never registered. This snippet
14
+ * dispatches a realistic `PointerEvent`/`MouseEvent` gesture
15
+ * (`pointerdown → mousedown → pointerup → mouseup`) and then triggers the
16
+ * activation with EXACTLY ONE click: native `el.click()` when the element has it
17
+ * (the trusted-path activation a `<button>` toggle listens for), else a single
18
+ * synthetic `MouseEvent("click")`. It must never do BOTH — a synthetic `click`
19
+ * dispatch plus a native `click()` fires a toggle handler twice
20
+ * (select → deselect = net zero), re-creating the very phantom this snippet
21
+ * exists to cure. Kept as a single interpolated string so all four primitives
22
+ * stay identical (DRY) rather than drifting copies.
23
+ */
24
+ /**
25
+ * Emits a browser-context statement block that activates the element bound to
26
+ * `elVar`: focus, then a `pointerdown → mousedown → pointerup → mouseup` gesture
27
+ * using real `MouseEvent`/`PointerEvent` constructors (feature-detecting
28
+ * `PointerEvent`, since a non-pointer environment still has `MouseEvent`),
29
+ * followed by EXACTLY ONE click activation.
30
+ *
31
+ * `elVar` is interpolated verbatim as an already-in-scope identifier — the
32
+ * caller resolves the element (e.g. `const el = matches[index]`) before
33
+ * interpolating this block. The single click is delivered via native
34
+ * `elVar.click()` when the element exposes one (every `HTMLElement` does; it is
35
+ * the trusted-path activation that drives React/Base Web toggle state), and via
36
+ * one synthetic `MouseEvent("click")` ONLY as the `else` for a non-`HTMLElement`
37
+ * that has no native `click()`. The two paths are mutually exclusive on purpose:
38
+ * dispatching a synthetic `click` AND calling native `click()` would fire the
39
+ * element's handler twice, and on a toggle that is select → deselect = net zero.
40
+ * The gesture events (down/up) are not click activations, so they never
41
+ * double-fire the handler.
42
+ */
43
+ export declare function clickActivationExpr(elVar: string): string;
44
+ //# sourceMappingURL=browser-click-expr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-click-expr.d.ts","sourceRoot":"","sources":["../../src/scraper/browser-click-expr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAsBzD"}
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ /**
3
+ * Shared browser-context click-activation snippet. Three primitives —
4
+ * `buildClickFrameCandidateExpr` (`deep-locator-scan.ts`),
5
+ * `buildDeepSubmitClickExpr` (`deep-query.ts`), and `buildClickByDeepIndexExpr`
6
+ * (`submit-control.ts`) — each need to activate a resolved element from inside
7
+ * a `page.evaluate`/`Frame.evaluate` string. They used to dispatch bare
8
+ * `new Event("mousedown"/"mouseup"/"click", { bubbles: true })`, which BUBBLES
9
+ * (so analytics/telemetry listeners fire) but is NOT a `MouseEvent`/`PointerEvent`
10
+ * instance — React's synthetic-event system and design-system widgets (Base Web,
11
+ * etc.) refuse a bare `Event` as a real user activation. The observed symptom on
12
+ * a markerless multi-select wizard: an option/toggle click reached the element
13
+ * and its analytics pixel recorded the click, yet the widget's "N selected"
14
+ * counter stayed flat because the selection never registered. This snippet
15
+ * dispatches a realistic `PointerEvent`/`MouseEvent` gesture
16
+ * (`pointerdown → mousedown → pointerup → mouseup`) and then triggers the
17
+ * activation with EXACTLY ONE click: native `el.click()` when the element has it
18
+ * (the trusted-path activation a `<button>` toggle listens for), else a single
19
+ * synthetic `MouseEvent("click")`. It must never do BOTH — a synthetic `click`
20
+ * dispatch plus a native `click()` fires a toggle handler twice
21
+ * (select → deselect = net zero), re-creating the very phantom this snippet
22
+ * exists to cure. Kept as a single interpolated string so all four primitives
23
+ * stay identical (DRY) rather than drifting copies.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.clickActivationExpr = clickActivationExpr;
27
+ /**
28
+ * Emits a browser-context statement block that activates the element bound to
29
+ * `elVar`: focus, then a `pointerdown → mousedown → pointerup → mouseup` gesture
30
+ * using real `MouseEvent`/`PointerEvent` constructors (feature-detecting
31
+ * `PointerEvent`, since a non-pointer environment still has `MouseEvent`),
32
+ * followed by EXACTLY ONE click activation.
33
+ *
34
+ * `elVar` is interpolated verbatim as an already-in-scope identifier — the
35
+ * caller resolves the element (e.g. `const el = matches[index]`) before
36
+ * interpolating this block. The single click is delivered via native
37
+ * `elVar.click()` when the element exposes one (every `HTMLElement` does; it is
38
+ * the trusted-path activation that drives React/Base Web toggle state), and via
39
+ * one synthetic `MouseEvent("click")` ONLY as the `else` for a non-`HTMLElement`
40
+ * that has no native `click()`. The two paths are mutually exclusive on purpose:
41
+ * dispatching a synthetic `click` AND calling native `click()` would fire the
42
+ * element's handler twice, and on a toggle that is select → deselect = net zero.
43
+ * The gesture events (down/up) are not click activations, so they never
44
+ * double-fire the handler.
45
+ */
46
+ function clickActivationExpr(elVar) {
47
+ return `{
48
+ if (typeof ${elVar}.focus === "function") { try { ${elVar}.focus(); } catch (e) {} }
49
+ const __ceOpts = { bubbles: true, cancelable: true, composed: true, view: (typeof window !== "undefined" ? window : undefined), button: 0 };
50
+ const __mouse = (type, buttons) => {
51
+ try { return new MouseEvent(type, Object.assign({}, __ceOpts, { buttons: buttons })); }
52
+ catch (e) { return new Event(type, { bubbles: true, cancelable: true }); }
53
+ };
54
+ const __pointer = (type, buttons) => {
55
+ if (typeof PointerEvent === "function") {
56
+ try { return new PointerEvent(type, Object.assign({}, __ceOpts, { buttons: buttons, pointerType: "mouse", isPrimary: true })); }
57
+ catch (e) {}
58
+ }
59
+ return __mouse(type, buttons);
60
+ };
61
+ ${elVar}.dispatchEvent(__pointer("pointerdown", 1));
62
+ ${elVar}.dispatchEvent(__mouse("mousedown", 1));
63
+ ${elVar}.dispatchEvent(__pointer("pointerup", 0));
64
+ ${elVar}.dispatchEvent(__mouse("mouseup", 0));
65
+ if (typeof ${elVar}.click === "function") { try { ${elVar}.click(); } catch (e) {} }
66
+ else { ${elVar}.dispatchEvent(__mouse("click", 0)); }
67
+ }`;
68
+ }
69
+ //# sourceMappingURL=browser-click-expr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-click-expr.js","sourceRoot":"","sources":["../../src/scraper/browser-click-expr.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;AAEH;;;;;;;;;;;;;;;;;;GAkBG;AACH,6BAAoC,KAAa;IAC/C,OAAO;iBACQ,KAAK,kCAAkC,KAAK;;;;;;;;;;;;;MAavD,KAAK;MACL,KAAK;MACL,KAAK;MACL,KAAK;iBACM,KAAK,kCAAkC,KAAK;aAChD,KAAK;IACd,CAAC;AACL,CAAC"}
@@ -34,6 +34,21 @@ export interface DeepLocatorTimeoutOptions {
34
34
  * probe.
35
35
  */
36
36
  frameTarget?: FrameTarget;
37
+ /**
38
+ * Forces {@link clickDeepLocatorCandidate} to skip the batched in-page
39
+ * synthetic click ({@link buildClickFrameCandidateExpr}, `isTrusted=false`)
40
+ * and activate ONLY via the trusted CDP `deepLocator().nth(index).click()`
41
+ * (`Input.dispatchMouseEvent`, `isTrusted=true`). The synthetic fast path is
42
+ * the default because it collapses the `index + 1` per-index resolve
43
+ * round-trips; a caller sets this ONLY on the phantom-driven retry, where the
44
+ * prior synthetic click already fired without effect and the per-index cost
45
+ * is worth paying to deliver a click a React/design-system handler accepts.
46
+ * Omitted/false everywhere else so throughput is unchanged for the common
47
+ * case. Does NOT suppress the not-actionable probe: an unrendered node still
48
+ * throws {@link isNodeNotActionableError} rather than paying a scaled-timeout
49
+ * CDP click.
50
+ */
51
+ preferTrustedClick?: boolean;
37
52
  }
38
53
  /**
39
54
  * One candidate element `page.deepLocator()` resolved inside a scoped frame.
@@ -59,6 +74,15 @@ export interface DeepLocatorCandidate {
59
74
  * enumeration fallback.
60
75
  */
61
76
  accessibleText: string;
77
+ /**
78
+ * `true` when the batched scan flagged this candidate as a navigation/advance
79
+ * control (BACK/Next/Cancel — see {@link IS_NAV_CANDIDATE_EXPR}). Feeds
80
+ * {@link scoreCandidate}'s nav-demotion tier so a "select '<option>'" step
81
+ * never resolves to the wizard's back/next button. Always `false` on the
82
+ * legacy per-candidate path (which can't read `data-testid`); there
83
+ * {@link scoreCandidate} re-derives the text-based portion of the nav check.
84
+ */
85
+ isNav: boolean;
62
86
  }
63
87
  /** One quoted phrase from an instruction, tagged with whether a negation marker (`NEGATION_MARKERS`) governs it. See {@link extractTaggedPhrases}. */
64
88
  export interface TaggedPhrase {
@@ -82,18 +106,41 @@ export interface TaggedPhrase {
82
106
  export declare function extractTaggedPhrases(instruction: string): TaggedPhrase[];
83
107
  /**
84
108
  * Scores one candidate's relevance to `instruction`'s tagged phrases, higher
85
- * is more relevant. Parallels `submit-control.ts`'s tiered-ranking shape:
86
- * negative signal is checked first and wins outright (a candidate matching
87
- * ANY negated phrase is actively demoted below "no match" a decoy sibling
88
- * button is worse than an unrelated structural node), then positive
89
- * exact/substring match tiers, falling through to 0 for empty or
90
- * unrelated text so a structural container with no accessible text can
91
- * never outrank a candidate whose text actually matches the instruction.
92
- * Exported so `flow-runner.ts` can detect a tie for the top rank among
93
- * `resolveDeepLocatorCandidates`'s already-sorted output (see
94
- * {@link extractTaggedPhrases}'s docblock).
109
+ * is more relevant. Parallels `submit-control.ts`'s tiered-ranking shape but
110
+ * adds two tiers the markerless-widget bug report needs: a nav/back demotion
111
+ * (so a "select '<option>'" step never lands on the wizard's BACK/Next button,
112
+ * whose own text may exact-match nothing OR be empty) and an ends-with tier (so
113
+ * an option whose accessible name is polluted by a leading icon-glyph name —
114
+ * an icon-font/`<svg><title>` prefix rendering as `"<IconName><Label>"` still
115
+ * beats a bare exact-text decoy by matching on the trailing label).
116
+ *
117
+ * Strict-priority tiers, first match wins:
118
+ * - negated-phrase match → `-2` (worst: a decoy sibling is worse than an
119
+ * unrelated structural node — the invariant the original tiering established),
120
+ * - exact positive → `4`,
121
+ * - ends-with a positive → `3` (the icon-glyph suffix case),
122
+ * - contains a positive (either direction) → `2`,
123
+ * - nav/back control with NO positive textual match → `-1`,
124
+ * - else → `0`.
125
+ *
126
+ * Crucially, the nav/back demotion sits BELOW the positive tiers, not above
127
+ * them: it only sinks a candidate that would otherwise score `0` (no phrase
128
+ * match at all) — the empty BACK button, or a bare "Next"/"Cancel" chrome
129
+ * button the instruction doesn't name. A candidate that positively matches the
130
+ * instruction phrase — exact, ends-with, or contains — is the control the step
131
+ * named and keeps its positive score even if its label happens to contain a nav
132
+ * word (`select 'Next'` → the "Next" option scores 4; "primary Next" whose step
133
+ * quotes 'Next' scores 2 via containment). This makes the demotion a tie-breaker
134
+ * against chrome, never an override of a real target.
135
+ *
136
+ * `isNav` comes from the batched scan (`data-testid` + empty-text signals it
137
+ * alone can see); the text-word portion is re-derived here via
138
+ * {@link matchesNavText} so the legacy per-candidate path (always `isNav=false`)
139
+ * still demotes a bare "Back"/"Next". Exported so `flow-runner.ts` can detect a
140
+ * tie for the top rank among `resolveDeepLocatorCandidates`'s already-sorted
141
+ * output (see {@link extractTaggedPhrases}'s docblock).
95
142
  */
96
- export declare function scoreCandidate(accessibleText: string, phrases: TaggedPhrase[]): number;
143
+ export declare function scoreCandidate(accessibleText: string, phrases: TaggedPhrase[], isNav?: boolean): number;
97
144
  /**
98
145
  * Enumerates every element `page.deepLocator()` matches inside the frame
99
146
  * scoped by `frameSelector`, ranked by relevance to `instruction` (highest
@@ -138,19 +185,34 @@ export declare function resolveDeepLocatorCandidates(page: Page, frameSelector:
138
185
  * must infer the outcome from whether this call throws plus their own
139
186
  * downstream DOM verification, not from a returned boolean.
140
187
  *
141
- * Prefers the one-round-trip {@link clickCandidateBatched} fast path when a
142
- * frame seam is available (`timeoutOptions.frameTarget`, or one resolved
143
- * internally the same way {@link scanFrameCandidatesBatched} does), falling
144
- * back to the legacy `DeepLocatorDelegate.click()` which never reports
145
- * success via a return value, only via not rejecting when no seam is
146
- * available, the batched call fails/degrades, or it reports the index
147
- * stale (`reason: "out-of-range"`). A batched `reason: "not-actionable"`
148
- * result throws an error {@link isNodeNotActionableError} classifies, the
149
- * same contract a real click against an unrendered node rejects with via the
150
- * CDP `-32000 Node does not have a layout object` error, so a caller
151
- * cascading through candidates treats both paths identically.
188
+ * By default, prefers the one-round-trip {@link clickCandidateBatched} fast
189
+ * path when a frame seam is available (`timeoutOptions.frameTarget`, or one
190
+ * resolved internally the same way {@link scanFrameCandidatesBatched} does):
191
+ * that batched click is a SYNTHETIC (`isTrusted=false`) activation, but it
192
+ * collapses the `index + 1` serial `nth(index)` resolve round-trips and works
193
+ * for the overwhelmingly common control. It falls back to the trusted
194
+ * `deepLocator().nth(index).click()` (understudy `Input.dispatchMouseEvent`,
195
+ * `isTrusted=true`) which never reports success via a return value, only via
196
+ * not rejecting when no seam is available, the batched call fails/degrades, or
197
+ * it reports the index stale (`reason: "out-of-range"`). A batched
198
+ * `reason: "not-actionable"` result throws an error {@link isNodeNotActionableError}
199
+ * classifies, the same contract a real click against an unrendered node rejects
200
+ * with via the CDP `-32000 Node does not have a layout object` error, so a
201
+ * caller cascading through candidates treats both paths identically.
202
+ *
203
+ * When `timeoutOptions.preferTrustedClick` is set, the synthetic batched click
204
+ * is SKIPPED entirely and activation goes straight to the trusted CDP
205
+ * `nth(index).click()` — the escalation a phantom-driven retry uses after a
206
+ * synthetic click fired without effect (a React/design-system handler that
207
+ * ignores untrusted activation). A cheap not-actionable probe still runs first
208
+ * so an unrendered candidate is skipped without paying the scaled-timeout CDP
209
+ * click.
210
+ *
211
+ * Resolves on success and rejects on failure — the caller must infer the
212
+ * outcome from whether this call throws plus their own downstream DOM
213
+ * verification, not from a returned boolean.
152
214
  *
153
- * The legacy fallback's watchdog scales with `index` (see
215
+ * The trusted-fallback watchdog scales with `index` (see
154
216
  * {@link DEEP_LOCATOR_CLICK_INDEX_ROUND_TRIP_MS}) so a legitimately-reachable
155
217
  * candidate isn't killed by a budget sized for a single round-trip. A
156
218
  * `click()` that still exceeds that scaled budget (a wedged CDP round-trip
@@ -1 +1 @@
1
- {"version":3,"file":"deep-locator-candidates.d.ts","sourceRoot":"","sources":["../../src/scraper/deep-locator-candidates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAWrD,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,wBAAwB,CAAC;AA2BhC,sJAAsJ;AACtJ,MAAM,WAAW,yBAAyB;IACxC,mIAAmI;IACnI,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uJAAuJ;IACvJ,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;;;;;;;;OAgBG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAKD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,oBAAoB;IACnC,kJAAkJ;IAClJ,KAAK,EAAE,MAAM,CAAC;IACd,gLAAgL;IAChL,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB;AAsBD,sJAAsJ;AACtJ,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,EAAE,CAaxE;AAOD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAStF;AA6JD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAC3B,cAAc,GAAE,yBAA8B,GAC7C,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAuCjC;AAqDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,cAAc,GAAE,yBAA8B,GAC7C,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED;;;;;;;;GAQG"}
1
+ {"version":3,"file":"deep-locator-candidates.d.ts","sourceRoot":"","sources":["../../src/scraper/deep-locator-candidates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAWrD,OAAO,EAEL,KAAK,WAAW,EAEjB,MAAM,wBAAwB,CAAC;AA2BhC,sJAAsJ;AACtJ,MAAM,WAAW,yBAAyB;IACxC,mIAAmI;IACnI,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uJAAuJ;IACvJ,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;;;;;;;;;;;OAgBG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B;;;;;;;;;;;;;OAaG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAKD;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,oBAAoB;IACnC,kJAAkJ;IAClJ,KAAK,EAAE,MAAM,CAAC;IACd,gLAAgL;IAChL,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAsBD,sJAAsJ;AACtJ,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,EAAE,CAaxE;AAkCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,cAAc,CAC5B,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,YAAY,EAAE,EACvB,KAAK,UAAQ,GACZ,MAAM,CAiBR;AA+JD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAC3B,cAAc,GAAE,yBAA8B,GAC7C,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAuCjC;AAwDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,cAAc,GAAE,yBAA8B,GAC7C,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED;;;;;;;;GAQG"}
@@ -89,31 +89,82 @@ function extractTaggedPhrases(instruction) {
89
89
  function normalize(text) {
90
90
  return text.replace(/\s+/g, " ").trim().toLowerCase();
91
91
  }
92
+ /**
93
+ * Nav/advance words that mark a control as chrome (BACK/Next/Cancel), matched
94
+ * with the same word-boundary predicate SHAPE `submit-control.ts`'s
95
+ * `NEGATIVE_TEXT_EXPR` uses, over a nav-word list that adds `"next"` (an advance
96
+ * button a "select '<option>'" step must be de-prioritized against). Kept here
97
+ * (not imported from that browser-context string) so {@link scoreCandidate} can
98
+ * re-derive the text portion of the nav check on the legacy per-candidate path,
99
+ * which can't read `data-testid` and so always arrives with `isNav === false`.
100
+ */
101
+ const NAV_TEXT_WORDS = [
102
+ "back",
103
+ "cancel",
104
+ "previous",
105
+ "next",
106
+ "close",
107
+ "save draft",
108
+ "save for later",
109
+ ];
110
+ /** True when `normalizedText` is one of {@link NAV_TEXT_WORDS} (whole-word / edge match), the text-only half of the scan's `IS_NAV_CANDIDATE_EXPR`. */
111
+ function matchesNavText(normalizedText) {
112
+ return NAV_TEXT_WORDS.some((n) => normalizedText === n || normalizedText.startsWith(`${n} `) || normalizedText.endsWith(` ${n}`));
113
+ }
92
114
  /**
93
115
  * Scores one candidate's relevance to `instruction`'s tagged phrases, higher
94
- * is more relevant. Parallels `submit-control.ts`'s tiered-ranking shape:
95
- * negative signal is checked first and wins outright (a candidate matching
96
- * ANY negated phrase is actively demoted below "no match" a decoy sibling
97
- * button is worse than an unrelated structural node), then positive
98
- * exact/substring match tiers, falling through to 0 for empty or
99
- * unrelated text so a structural container with no accessible text can
100
- * never outrank a candidate whose text actually matches the instruction.
101
- * Exported so `flow-runner.ts` can detect a tie for the top rank among
102
- * `resolveDeepLocatorCandidates`'s already-sorted output (see
103
- * {@link extractTaggedPhrases}'s docblock).
116
+ * is more relevant. Parallels `submit-control.ts`'s tiered-ranking shape but
117
+ * adds two tiers the markerless-widget bug report needs: a nav/back demotion
118
+ * (so a "select '<option>'" step never lands on the wizard's BACK/Next button,
119
+ * whose own text may exact-match nothing OR be empty) and an ends-with tier (so
120
+ * an option whose accessible name is polluted by a leading icon-glyph name —
121
+ * an icon-font/`<svg><title>` prefix rendering as `"<IconName><Label>"` still
122
+ * beats a bare exact-text decoy by matching on the trailing label).
123
+ *
124
+ * Strict-priority tiers, first match wins:
125
+ * - negated-phrase match → `-2` (worst: a decoy sibling is worse than an
126
+ * unrelated structural node — the invariant the original tiering established),
127
+ * - exact positive → `4`,
128
+ * - ends-with a positive → `3` (the icon-glyph suffix case),
129
+ * - contains a positive (either direction) → `2`,
130
+ * - nav/back control with NO positive textual match → `-1`,
131
+ * - else → `0`.
132
+ *
133
+ * Crucially, the nav/back demotion sits BELOW the positive tiers, not above
134
+ * them: it only sinks a candidate that would otherwise score `0` (no phrase
135
+ * match at all) — the empty BACK button, or a bare "Next"/"Cancel" chrome
136
+ * button the instruction doesn't name. A candidate that positively matches the
137
+ * instruction phrase — exact, ends-with, or contains — is the control the step
138
+ * named and keeps its positive score even if its label happens to contain a nav
139
+ * word (`select 'Next'` → the "Next" option scores 4; "primary Next" whose step
140
+ * quotes 'Next' scores 2 via containment). This makes the demotion a tie-breaker
141
+ * against chrome, never an override of a real target.
142
+ *
143
+ * `isNav` comes from the batched scan (`data-testid` + empty-text signals it
144
+ * alone can see); the text-word portion is re-derived here via
145
+ * {@link matchesNavText} so the legacy per-candidate path (always `isNav=false`)
146
+ * still demotes a bare "Back"/"Next". Exported so `flow-runner.ts` can detect a
147
+ * tie for the top rank among `resolveDeepLocatorCandidates`'s already-sorted
148
+ * output (see {@link extractTaggedPhrases}'s docblock).
104
149
  */
105
- function scoreCandidate(accessibleText, phrases) {
150
+ function scoreCandidate(accessibleText, phrases, isNav = false) {
106
151
  const normalizedText = normalize(accessibleText);
107
- if (!normalizedText)
108
- return 0;
109
152
  const positives = phrases.filter((p) => !p.negated).map((p) => normalize(p.text));
110
153
  const negatives = phrases.filter((p) => p.negated).map((p) => normalize(p.text));
111
- if (negatives.some((n) => n === normalizedText || normalizedText.includes(n)))
154
+ if (normalizedText.length > 0 &&
155
+ negatives.some((n) => n === normalizedText || normalizedText.includes(n))) {
156
+ return -2;
157
+ }
158
+ if (normalizedText.length > 0) {
159
+ if (positives.some((p) => p === normalizedText))
160
+ return 4;
161
+ if (positives.some((p) => normalizedText.endsWith(p)))
162
+ return 3;
163
+ if (positives.some((p) => normalizedText.includes(p) || p.includes(normalizedText)))
164
+ return 2;
165
+ }
166
+ if (isNav || matchesNavText(normalizedText))
112
167
  return -1;
113
- if (positives.some((p) => p === normalizedText))
114
- return 3;
115
- if (positives.some((p) => normalizedText.includes(p) || p.includes(normalizedText)))
116
- return 2;
117
168
  return 0;
118
169
  }
119
170
  /**
@@ -200,6 +251,7 @@ async function scanFrameCandidatesBatched(page, frameSelector, innerSelector, ho
200
251
  index: entry.index,
201
252
  selector: candidateSelector(hopSelector, entry.index),
202
253
  accessibleText: entry.text.trim(),
254
+ isNav: entry.isNav === true,
203
255
  }));
204
256
  }
205
257
  /**
@@ -238,6 +290,7 @@ async function enumerateCandidatesViaLegacyLoop(delegate, hopSelector, callTimeo
238
290
  index,
239
291
  selector: candidateSelector(hopSelector, index),
240
292
  accessibleText: accessibleText.trim(),
293
+ isNav: false,
241
294
  });
242
295
  }
243
296
  return candidates;
@@ -297,7 +350,7 @@ async function resolveDeepLocatorCandidates(page, frameSelector, innerSelector,
297
350
  .map((candidate, originalOrder) => ({
298
351
  candidate,
299
352
  originalOrder,
300
- score: scoreCandidate(candidate.accessibleText, phrases),
353
+ score: scoreCandidate(candidate.accessibleText, phrases, candidate.isNav),
301
354
  }))
302
355
  .sort((a, b) => b.score - a.score || a.originalOrder - b.originalOrder)
303
356
  .map(({ candidate }) => candidate);
@@ -317,10 +370,13 @@ function isFrameCandidateClickResult(entry) {
317
370
  * Batched-click fast path: one `frameTarget.evaluate(buildClickFrameCandidateExpr(innerSelector, index))`
318
371
  * round-trip replaces the legacy `nth(index).click()`, which (per
319
372
  * {@link DEEP_LOCATOR_CLICK_INDEX_ROUND_TRIP_MS}'s docs) pays `index + 1`
320
- * serial CDP round-trips through `resolveAtIndex`. Returns `null` (never
321
- * throws) when no frame seam is available, the evaluate call rejects, or the
322
- * resolved payload doesn't conform to {@link FrameCandidateClickResult}
323
- * every one of those degrades the caller to the legacy `nth(index).click()`
373
+ * serial CDP round-trips through `resolveAtIndex`. The batched click is a
374
+ * SYNTHETIC (`isTrusted=false`) activation; {@link clickDeepLocatorCandidate}
375
+ * escalates to the trusted CDP click only when this reports the index stale or
376
+ * the caller set `preferTrustedClick` (a phantom-driven retry). Returns `null`
377
+ * (never throws) when no frame seam is available, the evaluate call rejects, or
378
+ * the resolved payload doesn't conform to {@link FrameCandidateClickResult} —
379
+ * every one of those degrades the caller to the trusted `nth(index).click()`
324
380
  * path instead of losing the click, paralleling {@link scanFrameCandidatesBatched}'s
325
381
  * degrade contract on the enumeration side.
326
382
  */
@@ -351,19 +407,34 @@ async function clickCandidateBatched(page, frameSelector, innerSelector, index,
351
407
  * must infer the outcome from whether this call throws plus their own
352
408
  * downstream DOM verification, not from a returned boolean.
353
409
  *
354
- * Prefers the one-round-trip {@link clickCandidateBatched} fast path when a
355
- * frame seam is available (`timeoutOptions.frameTarget`, or one resolved
356
- * internally the same way {@link scanFrameCandidatesBatched} does), falling
357
- * back to the legacy `DeepLocatorDelegate.click()` which never reports
358
- * success via a return value, only via not rejecting when no seam is
359
- * available, the batched call fails/degrades, or it reports the index
360
- * stale (`reason: "out-of-range"`). A batched `reason: "not-actionable"`
361
- * result throws an error {@link isNodeNotActionableError} classifies, the
362
- * same contract a real click against an unrendered node rejects with via the
363
- * CDP `-32000 Node does not have a layout object` error, so a caller
364
- * cascading through candidates treats both paths identically.
410
+ * By default, prefers the one-round-trip {@link clickCandidateBatched} fast
411
+ * path when a frame seam is available (`timeoutOptions.frameTarget`, or one
412
+ * resolved internally the same way {@link scanFrameCandidatesBatched} does):
413
+ * that batched click is a SYNTHETIC (`isTrusted=false`) activation, but it
414
+ * collapses the `index + 1` serial `nth(index)` resolve round-trips and works
415
+ * for the overwhelmingly common control. It falls back to the trusted
416
+ * `deepLocator().nth(index).click()` (understudy `Input.dispatchMouseEvent`,
417
+ * `isTrusted=true`) which never reports success via a return value, only via
418
+ * not rejecting when no seam is available, the batched call fails/degrades, or
419
+ * it reports the index stale (`reason: "out-of-range"`). A batched
420
+ * `reason: "not-actionable"` result throws an error {@link isNodeNotActionableError}
421
+ * classifies, the same contract a real click against an unrendered node rejects
422
+ * with via the CDP `-32000 Node does not have a layout object` error, so a
423
+ * caller cascading through candidates treats both paths identically.
365
424
  *
366
- * The legacy fallback's watchdog scales with `index` (see
425
+ * When `timeoutOptions.preferTrustedClick` is set, the synthetic batched click
426
+ * is SKIPPED entirely and activation goes straight to the trusted CDP
427
+ * `nth(index).click()` — the escalation a phantom-driven retry uses after a
428
+ * synthetic click fired without effect (a React/design-system handler that
429
+ * ignores untrusted activation). A cheap not-actionable probe still runs first
430
+ * so an unrendered candidate is skipped without paying the scaled-timeout CDP
431
+ * click.
432
+ *
433
+ * Resolves on success and rejects on failure — the caller must infer the
434
+ * outcome from whether this call throws plus their own downstream DOM
435
+ * verification, not from a returned boolean.
436
+ *
437
+ * The trusted-fallback watchdog scales with `index` (see
367
438
  * {@link DEEP_LOCATOR_CLICK_INDEX_ROUND_TRIP_MS}) so a legitimately-reachable
368
439
  * candidate isn't killed by a budget sized for a single round-trip. A
369
440
  * `click()` that still exceeds that scaled budget (a wedged CDP round-trip
@@ -374,11 +445,20 @@ async function clickCandidateBatched(page, frameSelector, innerSelector, index,
374
445
  async function clickDeepLocatorCandidate(page, frameSelector, innerSelector, index, timeoutOptions = {}) {
375
446
  const callTimeoutMs = timeoutOptions.callTimeoutMs ?? DEFAULT_DEEP_LOCATOR_CALL_TIMEOUT_MS;
376
447
  const hopSelector = (0, frame_target_1.buildHopSelector)(frameSelector, innerSelector);
377
- const batchedResult = await clickCandidateBatched(page, frameSelector, innerSelector, index, hopSelector, timeoutOptions);
378
- if (batchedResult?.clicked)
379
- return;
380
- if (batchedResult?.reason === "not-actionable") {
381
- throw new Error(`deepLocator batched click for ${hopSelector} nth=${index}: node does not have a layout object`);
448
+ // The synthetic batched click is skipped when a trusted click is demanded —
449
+ // running BOTH would activate the element twice (on a toggle: select →
450
+ // deselect = net zero, the exact double-fire hazard browser-click-expr.ts
451
+ // warns about). Under preferTrustedClick the trusted `nth().click()` below is
452
+ // the sole activation, and an unrendered node surfaces as the CDP `-32000`
453
+ // error `isNodeNotActionableError` classifies rather than the batched probe's
454
+ // not-actionable reason.
455
+ if (!timeoutOptions.preferTrustedClick) {
456
+ const batchedResult = await clickCandidateBatched(page, frameSelector, innerSelector, index, hopSelector, timeoutOptions);
457
+ if (batchedResult?.reason === "not-actionable") {
458
+ throw new Error(`deepLocator batched click for ${hopSelector} nth=${index}: node does not have a layout object`);
459
+ }
460
+ if (batchedResult?.clicked)
461
+ return;
382
462
  }
383
463
  const scaledCallTimeoutMs = callTimeoutMs + index * deep_locator_scan_1.DEEP_LOCATOR_CLICK_INDEX_ROUND_TRIP_MS;
384
464
  await (0, watchdog_1.withWatchdog)(() => page.deepLocator(hopSelector).nth(index).click(), {
@@ -1 +1 @@
1
- {"version":3,"file":"deep-locator-candidates.js","sourceRoot":"","sources":["../../src/scraper/deep-locator-candidates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deep-locator-candidates.js","sourceRoot":"","sources":["../../src/scraper/deep-locator-candidates.ts"],"names":[],"mappings":"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"}
@@ -39,20 +39,45 @@ export declare const DEFAULT_CLICK_CANDIDATE_ATTEMPT_CAP = 5;
39
39
  export type ClickCandidateFn = (candidate: DeepLocatorCandidate) => Promise<void>;
40
40
  /** Refuses a candidate before it's clicked — e.g. `flow-runner.ts`'s `isWizardExitAction` deny-list, injected so this module stays site-agnostic. */
41
41
  export type DenyCandidatePredicate = (candidate: DeepLocatorCandidate) => boolean;
42
+ /**
43
+ * Reads the running "N selected" counter AFTER a candidate's click resolved,
44
+ * returning the current count or `null` when no counter is exposed. Injected so
45
+ * this module stays site-agnostic and `Page`-free — `flow-runner.ts` supplies a
46
+ * reader that re-snapshots the frame and parses the count via
47
+ * `selectionCountFromSignature`. See {@link ClickCandidateCascadeOptions.readSelectionCount}.
48
+ */
49
+ export type ReadSelectionCountFn = () => Promise<number | null>;
42
50
  export interface ClickCandidateCascadeOptions {
43
51
  /** Skips a candidate without clicking it when this returns `true`. Optional — omit to click every non-not-actionable candidate in rank order. */
44
52
  denyCandidate?: DenyCandidatePredicate;
45
53
  /** Overrides {@link DEFAULT_CLICK_CANDIDATE_ATTEMPT_CAP}. */
46
54
  attemptCap?: number;
55
+ /**
56
+ * When supplied (alongside a numeric {@link baselineSelectionCount}), a
57
+ * candidate whose click RESOLVED but did not raise the selection count above
58
+ * the baseline is treated like a not-actionable rejection: the walk keeps
59
+ * going to the next candidate instead of reporting success. This is the
60
+ * next-best-candidate recovery for a markerless multi-select phantom (the
61
+ * #163/#164 counter veto knows the click didn't register; this feeds that
62
+ * back into re-resolution before a replan is spent). A `null` read means "no
63
+ * counter exposed" and never vetoes, mirroring `isSelectionCounterStalled`'s
64
+ * null-safety. Omit for non-selection steps — the walk then behaves exactly
65
+ * as before.
66
+ */
67
+ readSelectionCount?: ReadSelectionCountFn;
68
+ /** The pre-walk selection count; a post-click read at or below this counts as "did not register". Ignored unless {@link readSelectionCount} is set. `null` disables the check (counter-less widget). */
69
+ baselineSelectionCount?: number | null;
47
70
  }
48
71
  /** Outcome of a {@link clickFirstActionableCandidate} walk. */
49
72
  export interface ClickCandidateCascadeOutcome {
50
- /** `true` only when a candidate's click resolved (didn't reject). */
73
+ /** `true` only when a candidate's click resolved (didn't reject) AND, when a selection-count check is wired, registered the selection. */
51
74
  clicked: boolean;
52
75
  /** The candidate that was clicked, or `null` when the walk exhausted the list/cap without a successful click. */
53
76
  candidate: DeepLocatorCandidate | null;
54
77
  /** Selectors of every candidate this walk actually clicked (attempted), in attempt order — denied candidates are excluded since they were never clicked. */
55
78
  triedSelectors: string[];
79
+ /** Selectors of candidates that clicked cleanly but were rejected because the selection counter did not rise (a subset of {@link triedSelectors}). Empty unless {@link ClickCandidateCascadeOptions.readSelectionCount} vetoed at least one — lets the caller emit a "clicked but nothing registered" failure reason distinct from not-actionable. */
80
+ counterStalledSelectors: string[];
56
81
  }
57
82
  /**
58
83
  * Walks `candidates` in rank order, clicking each via `click` until one
@@ -65,7 +90,20 @@ export interface ClickCandidateCascadeOutcome {
65
90
  * with actionability (a detached frame, a wedged click's
66
91
  * `WatchdogTimeoutError`). Never throws on exhaustion — an exhausted list
67
92
  * (every candidate denied or not-actionable, or the cap reached) resolves to
68
- * `{ clicked: false, candidate: null, triedSelectors }` instead.
93
+ * `{ clicked: false, candidate: null, triedSelectors, counterStalledSelectors }`
94
+ * instead.
95
+ *
96
+ * When `readSelectionCount`/`baselineSelectionCount` are supplied, a click that
97
+ * RESOLVED but left the selection count at or below the baseline is treated
98
+ * like a not-actionable rejection — the walk advances to the next candidate
99
+ * instead of reporting a phantom success. A count that rose returns immediately
100
+ * (so a click that DID register never triggers a second click — the
101
+ * toggle-double-click guard), and a `null` read is never a veto (counter-less
102
+ * widget). Because the check runs after `click` already awaited its own settle,
103
+ * a synchronously-updated counter is visible; the only residual is a genuinely-
104
+ * registered click whose counter lags, which is the same false-negative the
105
+ * caller's late counter veto already tolerates today — behaviour is no worse,
106
+ * and now recovers via the next candidate.
69
107
  */
70
108
  export declare function clickFirstActionableCandidate(candidates: readonly DeepLocatorCandidate[], click: ClickCandidateFn, options?: ClickCandidateCascadeOptions): Promise<ClickCandidateCascadeOutcome>;
71
109
  //# sourceMappingURL=deep-locator-click.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deep-locator-click.d.ts","sourceRoot":"","sources":["../../src/scraper/deep-locator-click.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAG9E;;;;;;;;;GASG;AACH,eAAO,MAAM,mCAAmC,IAAI,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAElF,qJAAqJ;AACrJ,MAAM,MAAM,sBAAsB,GAAG,CAAC,SAAS,EAAE,oBAAoB,KAAK,OAAO,CAAC;AAElF,MAAM,WAAW,4BAA4B;IAC3C,iJAAiJ;IACjJ,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,+DAA+D;AAC/D,MAAM,WAAW,4BAA4B;IAC3C,qEAAqE;IACrE,OAAO,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACvC,4JAA4J;IAC5J,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,6BAA6B,CACjD,UAAU,EAAE,SAAS,oBAAoB,EAAE,EAC3C,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,4BAA4B,CAAC,CAoBvC"}
1
+ {"version":3,"file":"deep-locator-click.d.ts","sourceRoot":"","sources":["../../src/scraper/deep-locator-click.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAG9E;;;;;;;;;GASG;AACH,eAAO,MAAM,mCAAmC,IAAI,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAElF,qJAAqJ;AACrJ,MAAM,MAAM,sBAAsB,GAAG,CAAC,SAAS,EAAE,oBAAoB,KAAK,OAAO,CAAC;AAElF;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAEhE,MAAM,WAAW,4BAA4B;IAC3C,iJAAiJ;IACjJ,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;OAWG;IACH,kBAAkB,CAAC,EAAE,oBAAoB,CAAC;IAC1C,wMAAwM;IACxM,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxC;AAED,+DAA+D;AAC/D,MAAM,WAAW,4BAA4B;IAC3C,0IAA0I;IAC1I,OAAO,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACvC,4JAA4J;IAC5J,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,sVAAsV;IACtV,uBAAuB,EAAE,MAAM,EAAE,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,6BAA6B,CACjD,UAAU,EAAE,SAAS,oBAAoB,EAAE,EAC3C,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE,4BAAiC,GACzC,OAAO,CAAC,4BAA4B,CAAC,CAmCvC"}