@testmuai/playwright-bindings 0.1.24 → 0.1.25-beta.1

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 (33) hide show
  1. package/dist/configure.d.ts +5 -0
  2. package/dist/configure.d.ts.map +1 -1
  3. package/dist/configure.js +1 -0
  4. package/dist/configure.js.map +1 -1
  5. package/dist/healPatch.d.ts +2 -0
  6. package/dist/healPatch.d.ts.map +1 -1
  7. package/dist/healPatch.js +127 -1
  8. package/dist/healPatch.js.map +1 -1
  9. package/dist/helpers/autohealAx.d.ts +25 -0
  10. package/dist/helpers/autohealAx.d.ts.map +1 -0
  11. package/dist/helpers/autohealAx.js +96 -0
  12. package/dist/helpers/autohealAx.js.map +1 -0
  13. package/dist/helpers/axTree/captureAxTree.d.ts +32 -0
  14. package/dist/helpers/axTree/captureAxTree.d.ts.map +1 -0
  15. package/dist/helpers/axTree/captureAxTree.js +109 -0
  16. package/dist/helpers/axTree/captureAxTree.js.map +1 -0
  17. package/dist/helpers/axTree/index.d.ts +8 -0
  18. package/dist/helpers/axTree/index.d.ts.map +1 -0
  19. package/dist/helpers/axTree/index.js +7 -0
  20. package/dist/helpers/axTree/index.js.map +1 -0
  21. package/dist/helpers/axTree/serializeAxTree.d.ts +82 -0
  22. package/dist/helpers/axTree/serializeAxTree.d.ts.map +1 -0
  23. package/dist/helpers/axTree/serializeAxTree.js +199 -0
  24. package/dist/helpers/axTree/serializeAxTree.js.map +1 -0
  25. package/dist/helpers/textualAnalyzer/heal.d.ts +1 -1
  26. package/dist/helpers/textualAnalyzer/heal.d.ts.map +1 -1
  27. package/dist/helpers/textualAnalyzer/heal.js +6 -3
  28. package/dist/helpers/textualAnalyzer/heal.js.map +1 -1
  29. package/dist/helpers/textualAnalyzer/index.d.ts +1 -0
  30. package/dist/helpers/textualAnalyzer/index.d.ts.map +1 -1
  31. package/dist/helpers/textualAnalyzer/index.js +2 -2
  32. package/dist/helpers/textualAnalyzer/index.js.map +1 -1
  33. package/package.json +1 -1
@@ -27,6 +27,11 @@ export interface ConfigureOptions {
27
27
  defaultNavigationTimeoutMs?: number;
28
28
  /** Opt-in marker — code-gen sets this for V4 KaneAI runs. Gates LT:Options.kaneRunV4 + preCmdVisual emission. */
29
29
  kaneRunV4?: boolean;
30
+ /** Global locator auto-heal version gate. Default '' keeps the vision heal
31
+ * path; code-gen sets configure({ autoHealVersion: 'AH2' }) to route failed
32
+ * actions through the AX-tree locator heal. Read by healPatch (mirrors PY's
33
+ * global `auto_heal_version` config — set once, read via configure.get). */
34
+ autoHealVersion?: string;
30
35
  }
31
36
  declare const DEFAULTS: Required<ConfigureOptions>;
32
37
  type ConfigKey = keyof typeof DEFAULTS;
@@ -1 +1 @@
1
- {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,KAAK,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,iHAAiH;IACjH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,QAAA,MAAM,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAmBxC,CAAC;AAEF,KAAK,SAAS,GAAG,MAAM,OAAO,QAAQ,CAAC;AAKvC,KAAK,aAAa,GAAG,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAGtD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAEhE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAUtD;AAED,wBAAgB,GAAG,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAErE;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAE9C;AAED,wBAAgB,MAAM,IAAI,IAAI,CAU7B"}
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC,aAAa,CAAC,EAAE,KAAK,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,iHAAiH;IACjH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;iFAG6E;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,QAAA,MAAM,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAoBxC,CAAC;AAEF,KAAK,SAAS,GAAG,MAAM,OAAO,QAAQ,CAAC;AAKvC,KAAK,aAAa,GAAG,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAGtD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAEhE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAUtD;AAED,wBAAgB,GAAG,CAAC,CAAC,SAAS,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAErE;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAE9C;AAED,wBAAgB,MAAM,IAAI,IAAI,CAU7B"}
package/dist/configure.js CHANGED
@@ -18,6 +18,7 @@ const DEFAULTS = {
18
18
  defaultActionTimeoutMs: 10000,
19
19
  defaultNavigationTimeoutMs: 30000,
20
20
  kaneRunV4: false,
21
+ autoHealVersion: '',
21
22
  };
22
23
  const data = { ...DEFAULTS };
23
24
  const setKeys = new Set();
@@ -1 +1 @@
1
- {"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AA+B/B,MAAM,QAAQ,GAA+B;IAC3C,SAAS,EAAE,KAAK;IAChB,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,EAAE;IACjB,gBAAgB,EAAE,KAAK;IACvB,SAAS,EAAE,EAAE;IACb,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,EAAE;IACnB,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,CAAC;IAChB,sBAAsB,EAAE,KAAK;IAC7B,0BAA0B,EAAE,KAAK;IACjC,SAAS,EAAE,KAAK;CACjB,CAAC;AAIF,MAAM,IAAI,GAA+B,EAAE,GAAG,QAAQ,EAAE,CAAC;AACzD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAa,CAAC;AAGrC,MAAM,KAAK,GAAoB,EAAE,CAAC;AAElC,MAAM,UAAU,sBAAsB,CAAC,IAAmB;IACxD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAsB;IAC9C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAgB,EAAE,CAAC;QACnD,IAAI,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,IAAI,CAAC,kCAAkC,GAAG,aAAa,CAAC,CAAC;YAC7D,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,GAAG,CAAsB,GAAM;IAC7C,OAAO,IAAI,CAAC,GAAG,CAAyB,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAc;IACnC,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAgB,EAAE,CAAC;QACvD,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAG,IAAmC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;aAClE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;YAAG,IAAmC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;;YAC3F,IAAmC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACvD,CAAC;IACD,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,uFAAuF;IACvF,4FAA4F;AAC9F,CAAC"}
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAoC/B,MAAM,QAAQ,GAA+B;IAC3C,SAAS,EAAE,KAAK;IAChB,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,EAAE;IACZ,QAAQ,EAAE,EAAE;IACZ,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,EAAE;IACjB,gBAAgB,EAAE,KAAK;IACvB,SAAS,EAAE,EAAE;IACb,UAAU,EAAE,EAAE;IACd,eAAe,EAAE,EAAE;IACnB,aAAa,EAAE,EAAE;IACjB,aAAa,EAAE,CAAC;IAChB,sBAAsB,EAAE,KAAK;IAC7B,0BAA0B,EAAE,KAAK;IACjC,SAAS,EAAE,KAAK;IAChB,eAAe,EAAE,EAAE;CACpB,CAAC;AAIF,MAAM,IAAI,GAA+B,EAAE,GAAG,QAAQ,EAAE,CAAC;AACzD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAa,CAAC;AAGrC,MAAM,KAAK,GAAoB,EAAE,CAAC;AAElC,MAAM,UAAU,sBAAsB,CAAC,IAAmB;IACxD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAsB;IAC9C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAgB,EAAE,CAAC;QACnD,IAAI,CAAC,CAAC,GAAG,IAAI,QAAQ,CAAC,EAAE,CAAC;YACvB,GAAG,CAAC,IAAI,CAAC,kCAAkC,GAAG,aAAa,CAAC,CAAC;YAC7D,SAAS;QACX,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,GAAG,CAAsB,GAAM;IAC7C,OAAO,IAAI,CAAC,GAAG,CAAyB,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAc;IACnC,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,MAAM;IACpB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAgB,EAAE,CAAC;QACvD,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;YAAG,IAAmC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;aAClE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;YAAG,IAAmC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;;YAC3F,IAAmC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACvD,CAAC;IACD,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,uFAAuF;IACvF,4FAA4F;AAC9F,CAAC"}
@@ -15,4 +15,6 @@ export declare function installHealPatch(samplePage: Page): void;
15
15
  * cleanup of the originals map.
16
16
  */
17
17
  export declare function _uninstallHealPatch(samplePage?: Page): void;
18
+ /** Test-only: reset the warn-once latch for an unrecognized autoHealVersion. */
19
+ export declare function _resetAhVersionWarned(): void;
18
20
  //# sourceMappingURL=healPatch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"healPatch.d.ts","sourceRoot":"","sources":["../src/healPatch.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAgB,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AA2GrD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAUvD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAU3D"}
1
+ {"version":3,"file":"healPatch.d.ts","sourceRoot":"","sources":["../src/healPatch.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAgB,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAmPrD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAUvD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAU3D;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C"}
package/dist/healPatch.js CHANGED
@@ -1,15 +1,102 @@
1
1
  import { currentStep, _getReporter } from './step.js';
2
2
  import { config } from './config.js';
3
+ import { get as getConfig } from './configure.js';
3
4
  import { getVisionCoordinates } from './helpers/vision.js';
4
- import { log } from './log.js';
5
+ import { runLocatorHeal } from './helpers/autohealAx.js';
6
+ import { log, repr } from './log.js';
5
7
  const HEAL_METHODS = [
6
8
  'click', 'dblclick', 'fill', 'type', 'press',
7
9
  'hover', 'check', 'uncheck', 'selectOption',
8
10
  'setInputFiles', 'scrollIntoViewIfNeeded', 'focus', 'tap',
9
11
  ];
10
12
  const COORD_METHODS = new Set(['click', 'dblclick', 'hover']);
13
+ // Maps a Locator method → the AH2 autoheal action_type enum
14
+ // (click | select | type | scroll). Mirrors PY's `_METHOD_TO_ACTION_TYPE`.
15
+ // Methods omitted (focus, and the JS-absent drag_to) skip AH2 entirely — the
16
+ // API has no action_type slot for them.
17
+ const METHOD_TO_ACTION_TYPE = {
18
+ click: 'click', dblclick: 'click', tap: 'click',
19
+ hover: 'click', check: 'click', uncheck: 'click',
20
+ fill: 'type', type: 'type', press: 'type', setInputFiles: 'type',
21
+ selectOption: 'select',
22
+ scrollIntoViewIfNeeded: 'scroll',
23
+ };
24
+ // Playwright methods whose options object is the SECOND positional arg (the
25
+ // first is a value: text / key / values / files). All other HEAL_METHODS take
26
+ // options as the FIRST arg. Used to inject a capped retry timeout at the right
27
+ // position (mirrors PY's `_capped_retry_kwargs`, which caps the `timeout` kwarg).
28
+ const OPTIONS_AT_INDEX_1 = new Set(['fill', 'type', 'press', 'selectOption', 'setInputFiles']);
29
+ const RETRY_TIMEOUT_CAP_MS = 5_000;
30
+ const DEFAULT_TIMEOUT_MS = 30_000;
31
+ /**
32
+ * Read the drifted selector off a Locator, defensively — the value the AH2
33
+ * heal endpoint receives as `previous_selectors`. Playwright JS stores it as
34
+ * a plain own-property `_selector` (empirically verified: `page.locator('#x')
35
+ * ._selector === '#x'`, xpath keeps its `xpath=` prefix; there is NO
36
+ * `_impl_obj` in JS — that was the Python path). Never throws.
37
+ *
38
+ * NOTE: `_selector` is a private Playwright internal — no public API exposes
39
+ * it. On a Playwright rename/removal this degrades to `""` (the heal still
40
+ * runs, it just loses the re-anchor hint); the real-`page.locator(...)`
41
+ * regression test in healPatchAh2.test.ts asserts non-empty extraction, so a
42
+ * rename fails CI loudly instead of silently dropping the hint.
43
+ */
44
+ function readDriftedSelector(loc) {
45
+ try {
46
+ const s = loc?._selector;
47
+ return typeof s === 'string' ? s : '';
48
+ }
49
+ catch {
50
+ return '';
51
+ }
52
+ }
53
+ /** Clone `args`, injecting a capped `timeout` into the method's options arg. */
54
+ function withCappedTimeout(name, args) {
55
+ const idx = OPTIONS_AT_INDEX_1.has(name) ? 1 : 0;
56
+ const next = args.slice();
57
+ const existing = next[idx] && typeof next[idx] === 'object' ? next[idx] : undefined;
58
+ const orig = existing?.['timeout'];
59
+ const capped = Math.min(typeof orig === 'number' ? orig : DEFAULT_TIMEOUT_MS, RETRY_TIMEOUT_CAP_MS);
60
+ next[idx] = { ...(existing ?? {}), timeout: capped };
61
+ return next;
62
+ }
63
+ /**
64
+ * AH2 branch: capture → heal → resolve a fresh locator → retry the SAME method
65
+ * on it. Applies to ALL HEAL_METHODS that map to an action type (not just the
66
+ * coord ones), since it yields a real fresh locator. The retry runs the
67
+ * UNWRAPPED `original` on the fresh locator (exactly like PY's heal-cache
68
+ * fast-path calls `original(fresh, ...)`) so it cannot recurse back into this
69
+ * wrapper. Never throws; returns `{ healed:false }` on any miss/failure so the
70
+ * caller falls through to the vision path / rethrows.
71
+ */
72
+ async function tryAh2LocatorHeal(loc, original, name, args, description) {
73
+ const page = loc.page();
74
+ const previous = readDriftedSelector(loc);
75
+ const actionType = METHOD_TO_ACTION_TYPE[name];
76
+ if (!actionType)
77
+ return { healed: false };
78
+ const healed = await runLocatorHeal(page, description, actionType, previous);
79
+ if (!healed)
80
+ return { healed: false };
81
+ const selector = healed.locatorType === 'xpath' ? `xpath=${healed.locator}` : healed.locator;
82
+ try {
83
+ const fresh = page.locator(selector);
84
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
+ const value = await original.apply(fresh, withCappedTimeout(name, args));
86
+ log.helper(`[heal] ${name} '${description}' → fresh locator ${selector.slice(0, 80)}`);
87
+ return { healed: true, value };
88
+ }
89
+ catch (e) {
90
+ log.warn(`[heal] retry on fresh locator ${selector} failed: ${e instanceof Error ? e.message : String(e)}`);
91
+ return { healed: false };
92
+ }
93
+ }
11
94
  const originals = new Map();
12
95
  let installed = false;
96
+ // Warn once (not per-action) when autoHealVersion is configured to a
97
+ // non-empty value that isn't the recognized 'AH2' — most likely a typo that
98
+ // would otherwise silently fall back to the legacy heal with no signal.
99
+ let ahVersionWarned = false;
13
100
  /**
14
101
  * Capture element rect via locator.boundingBox() and ship it via the
15
102
  * `lambda-element-bounds` action verb. Best-effort. Never raises — failure
@@ -54,6 +141,41 @@ function wrap(name, original) {
54
141
  catch (e) {
55
142
  const err = e;
56
143
  const strict = isStrictModeViolation(err);
144
+ // Warn once (not per-action) on a non-empty, unrecognized
145
+ // autoHealVersion — most likely a typo (e.g. 'AH3') that would
146
+ // otherwise silently fall back to the legacy heal below with no signal.
147
+ const ahVersion = getConfig('autoHealVersion');
148
+ if (ahVersion && ahVersion !== 'AH2' && !ahVersionWarned) {
149
+ log.warn(`[heal] unrecognized autoHealVersion=${repr(ahVersion)} — using legacy heal`);
150
+ ahVersionWarned = true;
151
+ }
152
+ // AH2 locator heal, gated by the GLOBAL config (mirror PY's global
153
+ // `auto_heal_version`): set once via configure({ autoHealVersion: 'AH2' })
154
+ // and read via configure.get — NOT a per-step opt. This branch is
155
+ // TERMINAL — it mirrors PY's `_default_heal` use_ax path: on a miss,
156
+ // `heal_fn` returns False and the wrapper does a bare `raise` of the
157
+ // ORIGINAL exception, with no other heal attempted. So here too: on ANY
158
+ // miss (runLocatorHeal returns null, or the fresh-locator retry itself
159
+ // fails), rethrow the original error immediately — we do NOT fall
160
+ // through to the (coord-only) vision heal below. A vision click landing
161
+ // somewhere would mask a genuine AH2 failure, which is exactly the
162
+ // fail-loud behavior PY's design avoids. When the global gate is off,
163
+ // this block is skipped entirely and the vision path stays byte-unchanged.
164
+ if (ahVersion === 'AH2' &&
165
+ METHOD_TO_ACTION_TYPE[name] &&
166
+ (strict || (err?.name === 'TimeoutError' && (await this.count()) === 0))) {
167
+ let outcome;
168
+ try {
169
+ outcome = await tryAh2LocatorHeal(this, original, name, args, stepInfo.description);
170
+ }
171
+ catch {
172
+ // tryAh2LocatorHeal never throws by contract; defensive only.
173
+ outcome = { healed: false };
174
+ }
175
+ if (outcome.healed)
176
+ return outcome.value;
177
+ throw e;
178
+ }
57
179
  // Heal on a timeout where the element is absent (count === 0), or a
58
180
  // strict-mode violation where the selector matched >1 element (count > 0
59
181
  // is expected, so skip the absence check). Both gated to coord-healable
@@ -134,4 +256,8 @@ export function _uninstallHealPatch(samplePage) {
134
256
  originals.clear();
135
257
  installed = false;
136
258
  }
259
+ /** Test-only: reset the warn-once latch for an unrecognized autoHealVersion. */
260
+ export function _resetAhVersionWarned() {
261
+ ahVersionWarned = false;
262
+ }
137
263
  //# sourceMappingURL=healPatch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"healPatch.js","sourceRoot":"","sources":["../src/healPatch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"healPatch.js","sourceRoot":"","sources":["../src/healPatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * AH2 standalone-binding heal client (TS mirror of the Python
3
+ * `testmu/_helpers/autoheal_ax.py`): capture the live AX tree → POST
4
+ * `/api/v1/AH2/autoheal` → resolve the returned `ref` → a fresh locator.
5
+ *
6
+ * This is the REPLAY-time counterpart to the runner's AH2 grounding: exported
7
+ * JS tests run inside customer CI with no runner process, so the whole
8
+ * capture → heal → resolve pipeline runs in-process here using the shared AX
9
+ * pipeline (`axTree/`) and the binding's own selector synthesis
10
+ * (`textualAnalyzer/locatorEnrichment.enrichElementLocator`).
11
+ *
12
+ * Returns `{ locator, locatorType, confidence, reasoning }` on a hit, or
13
+ * `null` on ANY miss (smart off, invalid action type, capture failed, non-200,
14
+ * no ref, confidence below floor, ref not in the table, enrichment failed,
15
+ * transport/other error). NEVER throws.
16
+ */
17
+ import type { Page } from 'playwright';
18
+ export interface LocatorHeal {
19
+ locator: string;
20
+ locatorType: string;
21
+ confidence: number;
22
+ reasoning: string;
23
+ }
24
+ export declare function runLocatorHeal(page: Page, actionInstruction: string, actionType: string, previousSelectors?: string, confidenceFloor?: number): Promise<LocatorHeal | null>;
25
+ //# sourceMappingURL=autohealAx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autohealAx.d.ts","sourceRoot":"","sources":["../../src/helpers/autohealAx.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,YAAY,CAAC;AAUnD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AA0CD,wBAAsB,cAAc,CAClC,IAAI,EAAE,IAAI,EACV,iBAAiB,EAAE,MAAM,EACzB,UAAU,EAAE,MAAM,EAClB,iBAAiB,SAAK,EACtB,eAAe,SAAM,GACpB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAiD7B"}
@@ -0,0 +1,96 @@
1
+ import { config } from '../config.js';
2
+ import { fetchWithAuth } from '../http.js';
3
+ import { log } from '../log.js';
4
+ import { captureAxTree } from './axTree/index.js';
5
+ import { enrichElementLocator } from './textualAnalyzer/locatorEnrichment.js';
6
+ const HEAL_TIMEOUT_MS = 60_000;
7
+ const VALID_ACTION_TYPES = new Set(['click', 'select', 'type', 'scroll']);
8
+ function healUrl() {
9
+ return config.current.aiApiHost.replace(/\/+$/, '') + '/api/v1/AH2/autoheal';
10
+ }
11
+ async function postAxHeal(url, body) {
12
+ try {
13
+ const resp = await fetchWithAuth(url, {
14
+ method: 'POST',
15
+ headers: { 'content-type': 'application/json' },
16
+ body: JSON.stringify(body),
17
+ signal: AbortSignal.timeout(HEAL_TIMEOUT_MS),
18
+ });
19
+ if (!resp.ok) {
20
+ log.helper(`[autoheal_ax] ${url} -> ${resp.status}`);
21
+ return null;
22
+ }
23
+ return (await resp.json());
24
+ }
25
+ catch (e) {
26
+ log.warn(`[autoheal_ax] transport error: ${e instanceof Error ? e.message : String(e)}`);
27
+ return null;
28
+ }
29
+ }
30
+ /**
31
+ * Resolve a live CDP session that can act on `frameId`'s nodes.
32
+ *
33
+ * v1 is main-frame-only (`captureAxTree` never inlines OOPIF content, so every
34
+ * ref carries `frame_id == ""`), so this always opens a fresh main-page
35
+ * session — identical to what the Python `resolve_session_for_frame` does for
36
+ * the `""` main-frame convention. Frame-scoped routing (the Python
37
+ * `_frame_capture.resolve_session_for_frame` OOPIF path) lands together with
38
+ * frame-aware capture as a documented follow-up. Caller owns detaching it.
39
+ */
40
+ async function resolveSessionForFrame(page, _frameId) {
41
+ return page.context().newCDPSession(page);
42
+ }
43
+ export async function runLocatorHeal(page, actionInstruction, actionType, previousSelectors = '', confidenceFloor = 0.7) {
44
+ if (!config.current.smart || !VALID_ACTION_TYPES.has(actionType))
45
+ return null;
46
+ try {
47
+ const captured = await captureAxTree(page);
48
+ if (captured === null)
49
+ return null;
50
+ const { doc, refTable } = captured;
51
+ const body = {
52
+ action_instruction: actionInstruction,
53
+ action_type: actionType,
54
+ dom_snapshot: doc,
55
+ previous_selectors: previousSelectors || '',
56
+ };
57
+ const resp = await postAxHeal(healUrl(), body);
58
+ if (!resp || !resp['ref'])
59
+ return null;
60
+ const confidence = Number(resp['confidence'] ?? 0);
61
+ if (confidence < confidenceFloor) {
62
+ log.helper(`[autoheal_ax] confidence ${confidence} < floor ${confidenceFloor}`);
63
+ return null;
64
+ }
65
+ const entry = refTable[String(resp['ref'])];
66
+ if (!entry || entry.backend_dom_node_id == null)
67
+ return null;
68
+ // Frame-scope: resolve on the ref's own frame CDP session (main frame for v1).
69
+ const cdp = await resolveSessionForFrame(page, entry.frame_id);
70
+ let enriched;
71
+ try {
72
+ enriched = await enrichElementLocator(cdp, { backendDomNodeId: entry.backend_dom_node_id });
73
+ }
74
+ finally {
75
+ try {
76
+ await cdp.detach();
77
+ }
78
+ catch {
79
+ /* ignore */
80
+ }
81
+ }
82
+ if (!enriched || !enriched.locator)
83
+ return null;
84
+ return {
85
+ locator: enriched.locator,
86
+ locatorType: enriched.locatorType ?? 'css',
87
+ confidence,
88
+ reasoning: typeof resp['reasoning'] === 'string' ? resp['reasoning'] : '',
89
+ };
90
+ }
91
+ catch (e) {
92
+ log.warn(`[autoheal_ax] unexpected: ${e instanceof Error ? e.message : String(e)}`);
93
+ return null;
94
+ }
95
+ }
96
+ //# sourceMappingURL=autohealAx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autohealAx.js","sourceRoot":"","sources":["../../src/helpers/autohealAx.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Main-frame AX capture → greppable doc + per-step ref table (TS).
3
+ *
4
+ * Mirrors the Python `testmu/_helpers/ax_tree/_capture.py` (`capture_ax_tree`)
5
+ * + `_accessibility.py` CDP path, but MAIN-FRAME ONLY for v1. The Python
6
+ * design's frame-aware capture (`_frame_capture.py` — same-process + OOPIF
7
+ * iframes inlined into one continuous ref space) is a documented follow-up
8
+ * here; this matches the v16-server's stated main-frame acceptance. The
9
+ * serializer (`serializeAxTree`) supports the frame-merge whole, so the
10
+ * `e<N>` doc + refTable format is already byte-identical to Python's
11
+ * frame-aware output — only the OOPIF *capture* is deferred.
12
+ *
13
+ * Plumbing mirrors `textualAnalyzer/domStructured.ts`: page.context()
14
+ * .newCDPSession → Accessibility.getFullAXTree → build the AxNode tree →
15
+ * serializeAxTree. Unlike domStructured it fetches NO bounding boxes (the
16
+ * serializer is a pure structural walk with no viewport filter — Python's
17
+ * capture passes skip_bounding_boxes=True on this path), and it normalizes
18
+ * CDP tri-state strings ("true"/"false"/"mixed") before rendering.
19
+ */
20
+ import type { Page } from 'playwright';
21
+ import { type RefTable } from './serializeAxTree.js';
22
+ /**
23
+ * Capture the page's main-frame AX document + per-step ref table.
24
+ *
25
+ * @returns `{ doc, refTable }`, or `null` when the tree is empty or capture
26
+ * fails (never throws).
27
+ */
28
+ export declare function captureAxTree(page: Page): Promise<{
29
+ doc: string;
30
+ refTable: RefTable;
31
+ } | null>;
32
+ //# sourceMappingURL=captureAxTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captureAxTree.d.ts","sourceRoot":"","sources":["../../../src/helpers/axTree/captureAxTree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,YAAY,CAAC;AAEnD,OAAO,EAAgC,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAqEnF;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAAG,IAAI,CAAC,CA+BnG"}
@@ -0,0 +1,109 @@
1
+ import { log } from '../../log.js';
2
+ import { serializeAxTree } from './serializeAxTree.js';
3
+ /** Extract a CDP property's `.value.value`, or null. */
4
+ function cdpProp(properties, name) {
5
+ if (!properties)
6
+ return null;
7
+ for (const p of properties) {
8
+ if (p['name'] === name) {
9
+ const v = p['value'];
10
+ return typeof v === 'object' && v !== null ? v.value ?? null : null;
11
+ }
12
+ }
13
+ return null;
14
+ }
15
+ /** A CDP AXValue's `.value` as a string. */
16
+ function axValue(node, key) {
17
+ const info = node[key];
18
+ return typeof info === 'object' && info !== null
19
+ ? String(info.value ?? '')
20
+ : '';
21
+ }
22
+ /**
23
+ * Normalize a tri-state AX value to true / false / "mixed" / null.
24
+ * CDP reports `checked`/`pressed` as the STRINGS "true"/"false"/"mixed"; the
25
+ * serializer's state rendering keys on real booleans / "mixed", so an
26
+ * unchecked box would otherwise render as [checked] (JS "false" is truthy).
27
+ * Mirrors Python `_normalize_tristate`.
28
+ */
29
+ function normalizeTristate(value) {
30
+ if (typeof value === 'boolean' || value == null)
31
+ return value ?? null;
32
+ if (typeof value === 'string') {
33
+ const lowered = value.trim().toLowerCase();
34
+ if (lowered === 'true')
35
+ return true;
36
+ if (lowered === 'false')
37
+ return false;
38
+ if (lowered === 'mixed')
39
+ return 'mixed';
40
+ }
41
+ return null;
42
+ }
43
+ function parseNode(node, byId) {
44
+ const props = node['properties'];
45
+ const children = [];
46
+ for (const cid of node['childIds'] ?? []) {
47
+ const child = byId.get(cid);
48
+ if (child)
49
+ children.push(parseNode(child, byId));
50
+ }
51
+ const levelRaw = cdpProp(props, 'level');
52
+ return {
53
+ role: axValue(node, 'role'),
54
+ name: axValue(node, 'name'),
55
+ value: axValue(node, 'value') || null,
56
+ url: cdpProp(props, 'url') ?? null,
57
+ level: typeof levelRaw === 'number' ? levelRaw : levelRaw != null ? Number(levelRaw) : null,
58
+ checked: normalizeTristate(cdpProp(props, 'checked')),
59
+ pressed: normalizeTristate(cdpProp(props, 'pressed')),
60
+ disabled: Boolean(cdpProp(props, 'disabled')),
61
+ selected: cdpProp(props, 'selected') ?? null,
62
+ expanded: cdpProp(props, 'expanded') ?? null,
63
+ required: Boolean(cdpProp(props, 'required')),
64
+ readonly: Boolean(cdpProp(props, 'readonly')),
65
+ focused: Boolean(cdpProp(props, 'focused')),
66
+ backendDomNodeId: node['backendDOMNodeId'] ?? null,
67
+ children,
68
+ };
69
+ }
70
+ /**
71
+ * Capture the page's main-frame AX document + per-step ref table.
72
+ *
73
+ * @returns `{ doc, refTable }`, or `null` when the tree is empty or capture
74
+ * fails (never throws).
75
+ */
76
+ export async function captureAxTree(page) {
77
+ let cdp = null;
78
+ try {
79
+ cdp = await page.context().newCDPSession(page);
80
+ const result = (await cdp.send('Accessibility.getFullAXTree', {}));
81
+ const nodes = result.nodes ?? [];
82
+ if (nodes.length === 0)
83
+ return null;
84
+ const byId = new Map();
85
+ for (const node of nodes) {
86
+ const nid = node['nodeId'];
87
+ if (nid)
88
+ byId.set(nid, node);
89
+ }
90
+ const root = nodes.find((n) => !n['parentId']) ?? nodes[0];
91
+ const tree = parseNode(root, byId);
92
+ return serializeAxTree(tree);
93
+ }
94
+ catch (e) {
95
+ log.warn(`[autoheal_ax] capture failed: ${e instanceof Error ? e.message : String(e)}`);
96
+ return null;
97
+ }
98
+ finally {
99
+ if (cdp) {
100
+ try {
101
+ await cdp.detach();
102
+ }
103
+ catch {
104
+ /* ignore */
105
+ }
106
+ }
107
+ }
108
+ }
109
+ //# sourceMappingURL=captureAxTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captureAxTree.js","sourceRoot":"","sources":["../../../src/helpers/axTree/captureAxTree.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,eAAe,EAA8B,MAAM,sBAAsB,CAAC;AAInF,wDAAwD;AACxD,SAAS,OAAO,CAAC,UAAsD,EAAE,IAAY;IACnF,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;YACrB,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAE,CAAyB,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/F,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,4CAA4C;AAC5C,SAAS,OAAO,CAAC,IAAa,EAAE,GAAW;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAC9C,CAAC,CAAC,MAAM,CAAE,IAA4B,CAAC,KAAK,IAAI,EAAE,CAAC;QACnD,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED;;;;;;GAMG;AACH,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,IAAI,IAAI;QAAE,OAAQ,KAAwB,IAAI,IAAI,CAAC;IAC1F,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,IAAI,OAAO,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QACpC,IAAI,OAAO,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QACtC,IAAI,OAAO,KAAK,OAAO;YAAE,OAAO,OAAO,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,IAAa,EAAE,IAA0B;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAA+C,CAAC;IAC/E,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAK,IAAI,CAAC,UAAU,CAA0B,IAAI,EAAE,EAAE,CAAC;QACnE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACzC,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;QAC3B,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;QAC3B,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI;QACrC,GAAG,EAAG,OAAO,CAAC,KAAK,EAAE,KAAK,CAAmB,IAAI,IAAI;QACrD,KAAK,EAAE,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;QAC3F,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACrD,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACrD,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC7C,QAAQ,EAAG,OAAO,CAAC,KAAK,EAAE,UAAU,CAAoB,IAAI,IAAI;QAChE,QAAQ,EAAG,OAAO,CAAC,KAAK,EAAE,UAAU,CAAoB,IAAI,IAAI;QAChE,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC7C,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC7C,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC3C,gBAAgB,EAAG,IAAI,CAAC,kBAAkB,CAAwB,IAAI,IAAI;QAC1E,QAAQ;KACT,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAU;IAC5C,IAAI,GAAG,GAAsB,IAAI,CAAC;IAClC,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAEhE,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAmB,CAAC;QACxC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAuB,CAAC;YACjD,IAAI,GAAG;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC;QAC5D,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACnC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,iCAAiC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACxF,OAAO,IAAI,CAAC;IACd,CAAC;YAAS,CAAC;QACT,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC;gBACH,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;YACrB,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * AX-tree capture + serialization for AH2 locator auto-heal (TS mirror of the
3
+ * Python `testmu/_helpers/ax_tree` package).
4
+ */
5
+ export { serializeAxTree, AX_DOC_MAX_CHARS, TEXT_TRUNCATE_CHARS } from './serializeAxTree.js';
6
+ export type { AxNode, FrameCapture, RefEntry, RefTable } from './serializeAxTree.js';
7
+ export { captureAxTree } from './captureAxTree.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/helpers/axTree/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC9F,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * AX-tree capture + serialization for AH2 locator auto-heal (TS mirror of the
3
+ * Python `testmu/_helpers/ax_tree` package).
4
+ */
5
+ export { serializeAxTree, AX_DOC_MAX_CHARS, TEXT_TRUNCATE_CHARS } from './serializeAxTree.js';
6
+ export { captureAxTree } from './captureAxTree.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/helpers/axTree/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE9F,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * AX-tree text serializer producing a greppable doc + per-step ref table.
3
+ *
4
+ * Byte-faithful TS port of the Python binding's
5
+ * `testmu/_helpers/ax_tree/_serializer.py` (`serialize_ax_tree`). The SAME
6
+ * `(doc, refTable)` format is consumed by the v16-server + controller
7
+ * (`/api/v1/AH2/autoheal` reads `doc`; the binding resolves refs off
8
+ * `refTable`), so the `e<N>` line format and refTable shape MUST stay
9
+ * byte-identical across both bindings.
10
+ *
11
+ * Pure — no I/O. The caller (`captureAxTree`) captures the `AxNode` tree via
12
+ * CDP before calling this.
13
+ *
14
+ * Frame-aware merge is ported whole (`frameChildren`): when the walk hits an
15
+ * `iframe`-role node it looks it up by the owning node's OWN backendDomNodeId
16
+ * (stable identity, never positional) and inlines the matched frame's content
17
+ * one indent deeper, marking `[frame f<N>]` on the owner line. Passing no
18
+ * `frameChildren` (or `[]`) reproduces the single-tree output byte-for-byte —
19
+ * the v1 `captureAxTree` is main-frame-only and always calls it that way; the
20
+ * merge machinery is here so the doc/refTable format is identical to Python's
21
+ * frame-aware output when OOPIF capture lands (documented follow-up).
22
+ */
23
+ export declare const AX_DOC_MAX_CHARS = 500000;
24
+ export declare const TEXT_TRUNCATE_CHARS = 200;
25
+ /**
26
+ * Duck-typed accessibility node — only the fields the serializer READS. Built
27
+ * from CDP by `captureAxTree`; mirrors the Python `AxNode` attributes the
28
+ * serializer duck-types on.
29
+ */
30
+ export interface AxNode {
31
+ role: string;
32
+ name: string;
33
+ children: AxNode[];
34
+ backendDomNodeId: number | null;
35
+ disabled?: boolean;
36
+ checked?: boolean | string | null;
37
+ expanded?: boolean | null;
38
+ selected?: boolean | null;
39
+ pressed?: boolean | string | null;
40
+ focused?: boolean;
41
+ required?: boolean;
42
+ readonly?: boolean;
43
+ level?: number | null;
44
+ url?: string | null;
45
+ value?: string | null;
46
+ }
47
+ /**
48
+ * Capture result for one iframe (mirrors Python `FrameCapture`). `status` is
49
+ * one of "captured" | "hidden" | "capture_failed" | "depth_exceeded" |
50
+ * "unresolved". `tree` is populated only when captured. `ownerBackendNodeId`
51
+ * is the owning iframe AX node's backendDomNodeId — the stable key the walk
52
+ * matches on (never positional).
53
+ */
54
+ export interface FrameCapture {
55
+ frameId: string;
56
+ status: string;
57
+ tree?: AxNode | null;
58
+ children?: FrameCapture[];
59
+ ownerBackendNodeId?: number | null;
60
+ }
61
+ export interface RefEntry {
62
+ backend_dom_node_id: number | null;
63
+ role: string;
64
+ name: string;
65
+ frame_id: string;
66
+ }
67
+ export type RefTable = Record<string, RefEntry>;
68
+ /**
69
+ * Serialize an accessibility tree into a greppable text doc + ref table.
70
+ *
71
+ * @param root The tree to walk (main frame).
72
+ * @param frameChildren Ordered FrameCaptures for iframes directly owned by
73
+ * `root`'s tree. `undefined`/`[]` reproduces single-tree output exactly.
74
+ * @returns `{ doc, refTable }` — `doc` one line per node; `refTable` maps each
75
+ * `e<N>` to `{ backend_dom_node_id, role, name, frame_id }` (`frame_id` is
76
+ * "" for the main frame).
77
+ */
78
+ export declare function serializeAxTree(root: AxNode, frameChildren?: FrameCapture[] | null): {
79
+ doc: string;
80
+ refTable: RefTable;
81
+ };
82
+ //# sourceMappingURL=serializeAxTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializeAxTree.d.ts","sourceRoot":"","sources":["../../../src/helpers/axTree/serializeAxTree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAUH,eAAO,MAAM,gBAAgB,SAAU,CAAC;AACxC,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAQvC;;;;GAIG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,QAAQ;IACvB,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAoDhD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,YAAY,EAAE,GAAG,IAAI,GACpC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAyGrC"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * AX-tree text serializer producing a greppable doc + per-step ref table.
3
+ *
4
+ * Byte-faithful TS port of the Python binding's
5
+ * `testmu/_helpers/ax_tree/_serializer.py` (`serialize_ax_tree`). The SAME
6
+ * `(doc, refTable)` format is consumed by the v16-server + controller
7
+ * (`/api/v1/AH2/autoheal` reads `doc`; the binding resolves refs off
8
+ * `refTable`), so the `e<N>` line format and refTable shape MUST stay
9
+ * byte-identical across both bindings.
10
+ *
11
+ * Pure — no I/O. The caller (`captureAxTree`) captures the `AxNode` tree via
12
+ * CDP before calling this.
13
+ *
14
+ * Frame-aware merge is ported whole (`frameChildren`): when the walk hits an
15
+ * `iframe`-role node it looks it up by the owning node's OWN backendDomNodeId
16
+ * (stable identity, never positional) and inlines the matched frame's content
17
+ * one indent deeper, marking `[frame f<N>]` on the owner line. Passing no
18
+ * `frameChildren` (or `[]`) reproduces the single-tree output byte-for-byte —
19
+ * the v1 `captureAxTree` is main-frame-only and always calls it that way; the
20
+ * merge machinery is here so the doc/refTable format is identical to Python's
21
+ * frame-aware output when OOPIF capture lands (documented follow-up).
22
+ */
23
+ /** The AX role Chrome assigns an <iframe>/<frame> element (compared lowercased). */
24
+ const FRAME_ROLE = 'iframe';
25
+ /** Pathology backstop, interpolated into the depth_exceeded note (mirrors Python). */
26
+ const FRAME_DEPTH_BACKSTOP = 10;
27
+ /** Structural/container roles carrying no info: skipped, children promoted to the same depth. */
28
+ const SKIP_ROLES = new Set(['none', 'generic', 'rootwebarea', 'webarea', 'inlinetextbox']);
29
+ export const AX_DOC_MAX_CHARS = 500_000;
30
+ export const TEXT_TRUNCATE_CHARS = 200;
31
+ const TRUNCATION_MARKER = '…[document truncated]';
32
+ // Column layout: "e<N>" + BASE_GAP spaces + (INDENT_PER_DEPTH * depth) spaces + role.
33
+ const BASE_GAP = 3;
34
+ const INDENT_PER_DEPTH = 2;
35
+ /** Index a level's FrameCaptures by their OWNER backendDomNodeId (drops null owners). */
36
+ function indexByOwner(frameChildren) {
37
+ const m = new Map();
38
+ for (const fc of frameChildren) {
39
+ if (fc.ownerBackendNodeId != null)
40
+ m.set(fc.ownerBackendNodeId, fc);
41
+ }
42
+ return m;
43
+ }
44
+ /** Truncate a name/value string at TEXT_TRUNCATE_CHARS, marking cuts with '…'. */
45
+ function truncate(text) {
46
+ if (text.length > TEXT_TRUNCATE_CHARS)
47
+ return text.slice(0, TEXT_TRUNCATE_CHARS) + '…';
48
+ return text;
49
+ }
50
+ /** Render sparse state tags in the fixed order required by the spec. */
51
+ function renderStates(node) {
52
+ const states = [];
53
+ if (node.disabled)
54
+ states.push('[disabled]');
55
+ if (node.checked === 'mixed')
56
+ states.push('[checked=mixed]');
57
+ else if (node.checked === true)
58
+ states.push('[checked]');
59
+ else if (node.checked === false)
60
+ states.push('[unchecked]');
61
+ if (node.expanded === true)
62
+ states.push('[expanded]');
63
+ else if (node.expanded === false)
64
+ states.push('[collapsed]');
65
+ if (node.selected)
66
+ states.push('[selected]');
67
+ if (node.pressed === 'mixed')
68
+ states.push('[pressed=mixed]');
69
+ else if (node.pressed === true)
70
+ states.push('[pressed]');
71
+ else if (node.pressed === false)
72
+ states.push('[unpressed]');
73
+ if (node.focused)
74
+ states.push('[focused]');
75
+ if (node.required)
76
+ states.push('[required]');
77
+ if (node.readonly)
78
+ states.push('[readonly]');
79
+ return states;
80
+ }
81
+ /** Render one doc line for an already-normalized (non-skipped) role. */
82
+ function renderLine(ref, depth, role, node) {
83
+ const gap = ' '.repeat(BASE_GAP + INDENT_PER_DEPTH * depth);
84
+ const name = truncate(node.name || '');
85
+ const extras = renderStates(node);
86
+ if (role === 'heading' && node.level != null)
87
+ extras.push(`level=${node.level}`);
88
+ else if (node.url)
89
+ extras.push(`url=${node.url}`);
90
+ if (node.value)
91
+ extras.push(`{value=${truncate(node.value)}}`);
92
+ let line = `${ref}${gap}${role} "${name}"`;
93
+ if (extras.length)
94
+ line += ' ' + extras.join(' ');
95
+ return line;
96
+ }
97
+ /**
98
+ * Serialize an accessibility tree into a greppable text doc + ref table.
99
+ *
100
+ * @param root The tree to walk (main frame).
101
+ * @param frameChildren Ordered FrameCaptures for iframes directly owned by
102
+ * `root`'s tree. `undefined`/`[]` reproduces single-tree output exactly.
103
+ * @returns `{ doc, refTable }` — `doc` one line per node; `refTable` maps each
104
+ * `e<N>` to `{ backend_dom_node_id, role, name, frame_id }` (`frame_id` is
105
+ * "" for the main frame).
106
+ */
107
+ export function serializeAxTree(root, frameChildren) {
108
+ const lines = [];
109
+ const refTable = {};
110
+ const state = { ref: 0, length: 0, truncated: false, frameNum: 0 };
111
+ function appendLine(line) {
112
+ const addedLen = line.length + (lines.length ? 1 : 0); // +1 for the joining newline
113
+ const charBudget = AX_DOC_MAX_CHARS - TRUNCATION_MARKER.length - 1;
114
+ if (state.length + addedLen > charBudget) {
115
+ state.truncated = true;
116
+ return false;
117
+ }
118
+ lines.push(line);
119
+ state.length += addedLen;
120
+ return true;
121
+ }
122
+ function renderFrame(fc, depth, frameNum) {
123
+ const gap = ' '.repeat(BASE_GAP + INDENT_PER_DEPTH * depth);
124
+ if (fc.status === 'unresolved') {
125
+ appendLine(`${gap}[frame ? unresolved — not captured]`);
126
+ return;
127
+ }
128
+ if (fc.status === 'hidden') {
129
+ appendLine(`${gap}[frame f${frameNum} hidden — not captured]`);
130
+ return;
131
+ }
132
+ if (fc.status === 'depth_exceeded') {
133
+ appendLine(`${gap}[frame f${frameNum} not captured — depth exceeds ${FRAME_DEPTH_BACKSTOP}]`);
134
+ return;
135
+ }
136
+ if (fc.status !== 'captured' || fc.tree == null) {
137
+ appendLine(`${gap}[frame f${frameNum} capture failed]`);
138
+ return;
139
+ }
140
+ const childrenByOwner = indexByOwner(fc.children ?? []);
141
+ walk(fc.tree, depth, fc.frameId, childrenByOwner);
142
+ }
143
+ function walk(node, depth, frameId, frameChildrenByOwner) {
144
+ if (state.truncated)
145
+ return;
146
+ const role = (node.role || '').trim().toLowerCase();
147
+ if (!role || SKIP_ROLES.has(role)) {
148
+ for (const child of node.children) {
149
+ walk(child, depth, frameId, frameChildrenByOwner);
150
+ if (state.truncated)
151
+ return;
152
+ }
153
+ return;
154
+ }
155
+ state.ref += 1;
156
+ const ref = `e${state.ref}`;
157
+ // Matched by the iframe node's OWN backendDomNodeId (stable identity),
158
+ // never by consuming an iterator positionally.
159
+ const fc = role === FRAME_ROLE && node.backendDomNodeId != null
160
+ ? frameChildrenByOwner.get(node.backendDomNodeId)
161
+ : undefined;
162
+ // Display number minted HERE, in document order — never carried in.
163
+ let frameNum = 0;
164
+ if (fc !== undefined) {
165
+ state.frameNum += 1;
166
+ frameNum = state.frameNum;
167
+ }
168
+ let line = renderLine(ref, depth, role, node);
169
+ if (fc !== undefined) {
170
+ line += fc.status === 'unresolved' ? ' [frame ?]' : ` [frame f${frameNum}]`;
171
+ }
172
+ if (!appendLine(line))
173
+ return;
174
+ refTable[ref] = {
175
+ backend_dom_node_id: node.backendDomNodeId,
176
+ role,
177
+ // Stripped at the source: downstream locator-enrichment strips the name
178
+ // before comparing against the DOM's accessible name.
179
+ name: (node.name || '').trim(),
180
+ frame_id: frameId,
181
+ };
182
+ if (fc !== undefined) {
183
+ renderFrame(fc, depth + 1, frameNum);
184
+ if (state.truncated)
185
+ return;
186
+ }
187
+ for (const child of node.children) {
188
+ walk(child, depth + 1, frameId, frameChildrenByOwner);
189
+ if (state.truncated)
190
+ return;
191
+ }
192
+ }
193
+ walk(root, 0, '', indexByOwner(frameChildren ?? []));
194
+ let doc = lines.join('\n');
195
+ if (state.truncated)
196
+ doc = doc ? `${doc}\n${TRUNCATION_MARKER}` : TRUNCATION_MARKER;
197
+ return { doc, refTable };
198
+ }
199
+ //# sourceMappingURL=serializeAxTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializeAxTree.js","sourceRoot":"","sources":["../../../src/helpers/axTree/serializeAxTree.ts"],"names":[],"mappings":"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"}
@@ -13,5 +13,5 @@ import type { Page } from 'playwright';
13
13
  export interface HealOutcome {
14
14
  value: string;
15
15
  }
16
- export declare function runHeal(page: Page, query: string, expectedValue: string | null, needsUnitConversion: boolean, condition?: string | null): Promise<HealOutcome | null>;
16
+ export declare function runHeal(page: Page, query: string, expectedValue: string | null, needsUnitConversion: boolean, condition?: string | null, previousCode?: string | null): Promise<HealOutcome | null>;
17
17
  //# sourceMappingURL=heal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"heal.d.ts","sourceRoot":"","sources":["../../../src/helpers/textualAnalyzer/heal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,IAAI,EAAiB,MAAM,YAAY,CAAC;AAWtD,MAAM,WAAW,WAAW;IAK1B,KAAK,EAAE,MAAM,CAAC;CACf;AAsCD,wBAAsB,OAAO,CAC3B,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,EAAE,mBAAmB,EAAE,OAAO,EACrF,SAAS,GAAE,MAAM,GAAG,IAAW,GAC9B,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAsC7B"}
1
+ {"version":3,"file":"heal.d.ts","sourceRoot":"","sources":["../../../src/helpers/textualAnalyzer/heal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,IAAI,EAAiB,MAAM,YAAY,CAAC;AAWtD,MAAM,WAAW,WAAW;IAK1B,KAAK,EAAE,MAAM,CAAC;CACf;AAyCD,wBAAsB,OAAO,CAC3B,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,EAAE,mBAAmB,EAAE,OAAO,EACrF,SAAS,GAAE,MAAM,GAAG,IAAW,EAAE,YAAY,GAAE,MAAM,GAAG,IAAW,GAClE,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAwC7B"}
@@ -9,7 +9,7 @@ const HEAL_TIMEOUT_MS = 60_000;
9
9
  function healUrl() {
10
10
  return config.current.aiApiHost.replace(/\/+$/, '') + '/api/v1/textual_analyzer/heal';
11
11
  }
12
- async function postHeal(query, domSnapshot, expectedValue, needsUnit, condition = null) {
12
+ async function postHeal(query, domSnapshot, expectedValue, needsUnit, condition = null, previousCode = null) {
13
13
  const body = {
14
14
  query,
15
15
  dom_snapshot: domSnapshot,
@@ -18,6 +18,9 @@ async function postHeal(query, domSnapshot, expectedValue, needsUnit, condition
18
18
  // Checkpoint condition drives in-code derivation on regen; without it the
19
19
  // heal would return a raw read for a derived (arithmetic/boolean) step.
20
20
  condition: condition ?? '',
21
+ // v3 re-anchoring: the recorded working code. Old servers ignore unknown
22
+ // keys; old recordings pass null -> '' (blind regen, unchanged).
23
+ previous_code: previousCode ?? '',
21
24
  };
22
25
  try {
23
26
  const resp = await fetchWithAuth(healUrl(), {
@@ -38,11 +41,11 @@ async function postHeal(query, domSnapshot, expectedValue, needsUnit, condition
38
41
  return null;
39
42
  }
40
43
  }
41
- export async function runHeal(page, query, expectedValue, needsUnitConversion, condition = null) {
44
+ export async function runHeal(page, query, expectedValue, needsUnitConversion, condition = null, previousCode = null) {
42
45
  const structured = await captureStructuredDom(page);
43
46
  if (structured == null || !structured.text)
44
47
  return null;
45
- const resp = await postHeal(query, structured.text, expectedValue, needsUnitConversion, condition);
48
+ const resp = await postHeal(query, structured.text, expectedValue, needsUnitConversion, condition, previousCode);
46
49
  if (!resp || !resp['code'])
47
50
  return null;
48
51
  const code = String(resp['code']);
@@ -1 +1 @@
1
- {"version":3,"file":"heal.js","sourceRoot":"","sources":["../../../src/helpers/textualAnalyzer/heal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"heal.js","sourceRoot":"","sources":["../../../src/helpers/textualAnalyzer/heal.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ export interface TextualAnalyzerOptions {
19
19
  operator?: string;
20
20
  transforms?: string[];
21
21
  condition?: string | null;
22
+ codeJs?: string | null;
22
23
  }
23
24
  /**
24
25
  * Execute a recorded textual_visual extraction, healing on locator drift.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/helpers/textualAnalyzer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,IAAI,EAAiB,MAAM,YAAY,CAAC;AAStD,qBAAa,yBAA0B,SAAQ,KAAK;CAAG;AAEvD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAsBD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBtG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/helpers/textualAnalyzer/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,IAAI,EAAiB,MAAM,YAAY,CAAC;AAStD,qBAAa,yBAA0B,SAAQ,KAAK;CAAG;AAEvD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAsBD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2BtG"}
@@ -31,7 +31,7 @@ async function staleAndHandles(page, locators) {
31
31
  * Returns the extracted value (string; transforms applied downstream as today).
32
32
  */
33
33
  export async function textualAnalyzer(page, opts) {
34
- const { wrappedJs, locators, query, expectedValue = null, needsUnitConversion = false, condition = null } = opts;
34
+ const { wrappedJs, locators, query, expectedValue = null, needsUnitConversion = false, condition = null, codeJs = null, } = opts;
35
35
  const { stale, handles } = await staleAndHandles(page, locators);
36
36
  // Happy path — every recorded locator visible.
37
37
  if (stale.length === 0 && handles.length === locators.length) {
@@ -40,7 +40,7 @@ export async function textualAnalyzer(page, opts) {
40
40
  // Drift — regenerate the whole extraction.
41
41
  log.helper(`[textual_analyzer] ${stale.length}/${locators.length} locators not visible -> heal ` +
42
42
  `(query=${repr(preview(query, 60).replace(/\.\.\.$/, ''))})`);
43
- const outcome = await runHeal(page, query, expectedValue, needsUnitConversion, condition);
43
+ const outcome = await runHeal(page, query, expectedValue, needsUnitConversion, condition, codeJs);
44
44
  if (outcome == null) {
45
45
  throw new TextualAnalyzerHealFailed(`textualAnalyzer could not heal extraction for query=${repr(query)}; stale locators: ${JSON.stringify(stale)}`);
46
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/helpers/textualAnalyzer/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,gFAAgF;AAChF,iFAAiF;AACjF,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,MAAM,OAAO,yBAA0B,SAAQ,KAAK;CAAG;AAavD,KAAK,UAAU,eAAe,CAC5B,IAAU,EAAE,QAAkB;IAE9B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;YAC5C,IAAI,MAAM,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;;gBAC/B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,mCAAmC;YACnC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAU,EAAE,IAA4B;IAC5E,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,EAAE,mBAAmB,GAAG,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAEjH,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEjE,+CAA+C;IAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC7D,OAAO,CAAC,MAAM,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAkB,CAAC;IAC5E,CAAC;IAED,2CAA2C;IAC3C,GAAG,CAAC,MAAM,CACR,sBAAsB,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,gCAAgC;QACrF,UAAU,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAC7D,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,SAAS,CAAC,CAAC;IAC1F,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,yBAAyB,CACjC,uDAAuD,IAAI,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAC/G,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,8CAA8C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChF,OAAO,OAAO,CAAC,KAAK,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/helpers/textualAnalyzer/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,gFAAgF;AAChF,iFAAiF;AACjF,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,MAAM,OAAO,yBAA0B,SAAQ,KAAK;CAAG;AAcvD,KAAK,UAAU,eAAe,CAC5B,IAAU,EAAE,QAAkB;IAE9B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC,CAAC;YACxE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;YAC5C,IAAI,MAAM,IAAI,IAAI;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;;gBAC/B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,mCAAmC;YACnC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAU,EAAE,IAA4B;IAC5E,MAAM,EACJ,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,EAAE,mBAAmB,GAAG,KAAK,EAC7E,SAAS,GAAG,IAAI,EAAE,MAAM,GAAG,IAAI,GAChC,GAAG,IAAI,CAAC;IAET,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEjE,+CAA+C;IAC/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC7D,OAAO,CAAC,MAAM,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAkB,CAAC;IAC5E,CAAC;IAED,2CAA2C;IAC3C,GAAG,CAAC,MAAM,CACR,sBAAsB,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,gCAAgC;QACrF,UAAU,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAC7D,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAClG,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,yBAAyB,CACjC,uDAAuD,IAAI,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAC/G,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,MAAM,CAAC,8CAA8C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChF,OAAO,OAAO,CAAC,KAAK,CAAC;AACvB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testmuai/playwright-bindings",
3
- "version": "0.1.24",
3
+ "version": "0.1.25-beta.1",
4
4
  "description": "Testmu binding for Playwright — thin runtime for LambdaTest exports",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",